crossplane-function-pythonic 0.6.3__py3-none-any.whl → 0.7.0__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.
- crossplane/pythonic/__about__.py +1 -3
- crossplane/pythonic/auto_ready.py +31 -22
- crossplane/pythonic/command.py +31 -24
- crossplane/pythonic/composite.py +589 -386
- crossplane/pythonic/function.py +61 -40
- crossplane/pythonic/grpc.py +4 -3
- crossplane/pythonic/main.py +7 -3
- crossplane/pythonic/packages.py +27 -19
- crossplane/pythonic/proto/v1/run_function_pb2.pyi +1121 -255
- crossplane/pythonic/proto/v1/run_function_pb2_grpc.py +1 -1
- crossplane/pythonic/proto/v1/run_function_pb2_grpc.pyi +64 -0
- crossplane/pythonic/protobuf.py +346 -196
- crossplane/pythonic/render.py +206 -81
- crossplane/pythonic/version.py +1 -1
- {crossplane_function_pythonic-0.6.3.dist-info → crossplane_function_pythonic-0.7.0.dist-info}/METADATA +4 -4
- crossplane_function_pythonic-0.7.0.dist-info/RECORD +22 -0
- {crossplane_function_pythonic-0.6.3.dist-info → crossplane_function_pythonic-0.7.0.dist-info}/WHEEL +1 -1
- crossplane/pythonic/diff.py +0 -880
- crossplane_function_pythonic-0.6.3.dist-info/RECORD +0 -22
- {crossplane_function_pythonic-0.6.3.dist-info → crossplane_function_pythonic-0.7.0.dist-info}/entry_points.txt +0 -0
crossplane/pythonic/render.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import argparse
|
|
1
2
|
import asyncio
|
|
2
3
|
import importlib
|
|
3
4
|
import inspect
|
|
@@ -5,10 +6,13 @@ import json
|
|
|
5
6
|
import logging
|
|
6
7
|
import pathlib
|
|
7
8
|
import sys
|
|
9
|
+
import typing
|
|
10
|
+
from typing import cast
|
|
8
11
|
|
|
9
12
|
import inflect
|
|
10
13
|
import kr8s
|
|
11
14
|
import yaml
|
|
15
|
+
from kr8s._api import Api
|
|
12
16
|
|
|
13
17
|
from . import (
|
|
14
18
|
command,
|
|
@@ -27,7 +31,7 @@ class Command(command.Command):
|
|
|
27
31
|
help = "Render a function-pythonic Composition"
|
|
28
32
|
|
|
29
33
|
@classmethod
|
|
30
|
-
def add_parser_arguments(cls, parser):
|
|
34
|
+
def add_parser_arguments(cls, parser: argparse.ArgumentParser) -> None:
|
|
31
35
|
cls.add_function_arguments(parser)
|
|
32
36
|
parser.add_argument(
|
|
33
37
|
"composite",
|
|
@@ -113,16 +117,16 @@ class Command(command.Command):
|
|
|
113
117
|
help="Include the context in the rendered output as a resource of kind: Context.",
|
|
114
118
|
)
|
|
115
119
|
|
|
116
|
-
def initialize(self):
|
|
117
|
-
if self.args:
|
|
120
|
+
def initialize(self) -> None:
|
|
121
|
+
if vars(self.args):
|
|
118
122
|
self.initialize_function()
|
|
119
123
|
self.logger = logging.getLogger(__name__)
|
|
120
124
|
|
|
121
|
-
async def run(self):
|
|
125
|
+
async def run(self) -> None:
|
|
122
126
|
if self.args.kube_context:
|
|
123
|
-
api = await kr8s.asyncio.api(context=self.args.kube_context)
|
|
127
|
+
api: Api | None = await kr8s.asyncio.api(context=self.args.kube_context)
|
|
124
128
|
else:
|
|
125
|
-
api = None
|
|
129
|
+
api: Api | None = None
|
|
126
130
|
composite = await self.setup_composite(api)
|
|
127
131
|
observed = self.collect_resources(self.args.observed_resources)
|
|
128
132
|
composition = await self.setup_composition(composite, api)
|
|
@@ -180,13 +184,14 @@ class Command(command.Command):
|
|
|
180
184
|
print("---")
|
|
181
185
|
print(str(render.context), end="")
|
|
182
186
|
|
|
183
|
-
async def setup_composite(self, api=None):
|
|
187
|
+
async def setup_composite(self, api=Api | None) -> protobuf.Value:
|
|
184
188
|
# Obtain the Composite to render.
|
|
185
189
|
if self.args.composite.is_file():
|
|
186
|
-
return protobuf.Yaml(self.args.composite.read_text())
|
|
190
|
+
return cast(protobuf.Value, protobuf.Yaml(self.args.composite.read_text()))
|
|
187
191
|
if not api:
|
|
188
192
|
print(f'Composite "{self.args.composite}" is not a file', file=sys.stderr)
|
|
189
193
|
sys.exit(1)
|
|
194
|
+
return
|
|
190
195
|
composite = str(self.args.composite).split(":")
|
|
191
196
|
if len(composite) == 3:
|
|
192
197
|
namespace = None
|
|
@@ -202,14 +207,16 @@ class Command(command.Command):
|
|
|
202
207
|
)
|
|
203
208
|
sys.exit(1)
|
|
204
209
|
composite = await self.kr8s_get(
|
|
205
|
-
api, composite[0], composite[1], namespace, composite[-1]
|
|
210
|
+
cast(Api, api), composite[0], composite[1], namespace, composite[-1]
|
|
206
211
|
)
|
|
207
212
|
if not composite:
|
|
208
213
|
print(f'Composite "{self.args.composite}" not found', file=sys.stderr)
|
|
209
214
|
sys.exit(1)
|
|
210
215
|
return composite
|
|
211
216
|
|
|
212
|
-
async def setup_composition(
|
|
217
|
+
async def setup_composition(
|
|
218
|
+
self, composite: protobuf.Value, api: Api | None = None
|
|
219
|
+
) -> protobuf.Value | None:
|
|
213
220
|
# Obtain the Composition that will be used to render the Composite.
|
|
214
221
|
if not self.args.composition:
|
|
215
222
|
return None
|
|
@@ -217,7 +224,7 @@ class Command(command.Command):
|
|
|
217
224
|
composition = self.args.composition.read_text()
|
|
218
225
|
if self.args.composition.suffix == ".py":
|
|
219
226
|
return self.create_composition(composite, composition)
|
|
220
|
-
composition = protobuf.Yaml(composition)
|
|
227
|
+
composition = cast(protobuf.Value, protobuf.Yaml(composition))
|
|
221
228
|
if not len(composition.spec.pipeline):
|
|
222
229
|
print(
|
|
223
230
|
f"Composition file does not contain any pipeline steps: {self.args.composition}",
|
|
@@ -262,7 +269,9 @@ class Command(command.Command):
|
|
|
262
269
|
sys.exit(1)
|
|
263
270
|
return self.create_composition(composite, self.args.composition)
|
|
264
271
|
|
|
265
|
-
def create_composition(
|
|
272
|
+
def create_composition(
|
|
273
|
+
self, composite: protobuf.Value, module: str = ""
|
|
274
|
+
) -> protobuf.Value:
|
|
266
275
|
composition = protobuf.Map()
|
|
267
276
|
composition.apiVersion = "apiextensions.crossplane.io/v1"
|
|
268
277
|
composition.kind = "Composition"
|
|
@@ -279,7 +288,7 @@ class Command(command.Command):
|
|
|
279
288
|
composition.spec.pipeline[0].input.composite = str(module)
|
|
280
289
|
return composition
|
|
281
290
|
|
|
282
|
-
def collect_resources(self, entries):
|
|
291
|
+
def collect_resources(self, entries: list[pathlib.Path]) -> list[protobuf.Value]:
|
|
283
292
|
resources = []
|
|
284
293
|
for entry in entries:
|
|
285
294
|
if entry.is_file():
|
|
@@ -299,7 +308,7 @@ class Command(command.Command):
|
|
|
299
308
|
resources.sort(key=lambda resource: str(resource.metadata.name))
|
|
300
309
|
return resources
|
|
301
310
|
|
|
302
|
-
def collect_schemas(self, entries):
|
|
311
|
+
def collect_schemas(self, entries: list[pathlib.Path]) -> list[protobuf.Value]:
|
|
303
312
|
schemas = []
|
|
304
313
|
for entry in entries:
|
|
305
314
|
if entry.is_file():
|
|
@@ -318,7 +327,7 @@ class Command(command.Command):
|
|
|
318
327
|
sys.exit(1)
|
|
319
328
|
return schemas
|
|
320
329
|
|
|
321
|
-
def setup_context(self):
|
|
330
|
+
def setup_context(self) -> protobuf.Value:
|
|
322
331
|
# Load the request context with any specified command line options.
|
|
323
332
|
context = protobuf.Map()
|
|
324
333
|
for entry in self.args.context_files:
|
|
@@ -341,17 +350,17 @@ class Command(command.Command):
|
|
|
341
350
|
|
|
342
351
|
async def render(
|
|
343
352
|
self,
|
|
344
|
-
composite,
|
|
345
|
-
observed=None,
|
|
346
|
-
composition=None,
|
|
347
|
-
resources=None,
|
|
348
|
-
schemas=None,
|
|
349
|
-
context=None,
|
|
350
|
-
api=None,
|
|
351
|
-
render_unknowns=False,
|
|
352
|
-
crossplane_v1=False,
|
|
353
|
-
composite_observeds=False,
|
|
354
|
-
):
|
|
353
|
+
composite: protobuf.Value,
|
|
354
|
+
observed: list[protobuf.Value] | None = None,
|
|
355
|
+
composition: protobuf.Value | None = None,
|
|
356
|
+
resources: list[protobuf.Value] | None = None,
|
|
357
|
+
schemas: list[protobuf.Value] | None = None,
|
|
358
|
+
context: protobuf.Value | None = None,
|
|
359
|
+
api: Api | None = None,
|
|
360
|
+
render_unknowns: bool = False,
|
|
361
|
+
crossplane_v1: bool = False,
|
|
362
|
+
composite_observeds: bool = False,
|
|
363
|
+
) -> protobuf.Value | None:
|
|
355
364
|
# Create the request used when running Composition steps.
|
|
356
365
|
if schemas is None:
|
|
357
366
|
schemas = []
|
|
@@ -369,7 +378,9 @@ class Command(command.Command):
|
|
|
369
378
|
request.context = context
|
|
370
379
|
|
|
371
380
|
# Establish the request observed composite.
|
|
372
|
-
await self.set_resource(
|
|
381
|
+
await self.set_resource(
|
|
382
|
+
composite, cast(protobuf.Value, request.observed.composite), resources, api
|
|
383
|
+
)
|
|
373
384
|
# Establish the manually configured observed resources.
|
|
374
385
|
if observed:
|
|
375
386
|
async with asyncio.TaskGroup() as group:
|
|
@@ -381,7 +392,7 @@ class Command(command.Command):
|
|
|
381
392
|
group.create_task(
|
|
382
393
|
self.set_resource(
|
|
383
394
|
resource,
|
|
384
|
-
request.observed.resources[name],
|
|
395
|
+
cast(protobuf.Value, request.observed.resources[name]),
|
|
385
396
|
resources,
|
|
386
397
|
api,
|
|
387
398
|
)
|
|
@@ -489,34 +500,49 @@ class Command(command.Command):
|
|
|
489
500
|
for requirement in step.requirements.requiredResources:
|
|
490
501
|
await self.set_required(
|
|
491
502
|
requirement.requirementName,
|
|
492
|
-
requirement,
|
|
493
|
-
request.required_resources,
|
|
503
|
+
self.requirement_selector(requirement),
|
|
504
|
+
cast(protobuf.MapMessage, request.required_resources),
|
|
494
505
|
resources,
|
|
495
506
|
api,
|
|
496
507
|
)
|
|
497
508
|
# Fetch the required resources requested.
|
|
498
509
|
for name, selector in requirements.resources:
|
|
499
510
|
await self.set_required(
|
|
500
|
-
name,
|
|
511
|
+
name,
|
|
512
|
+
selector,
|
|
513
|
+
cast(protobuf.MapMessage, request.required_resources),
|
|
514
|
+
resources,
|
|
515
|
+
api,
|
|
501
516
|
)
|
|
502
517
|
# Fetch the now deprecated extra resources requested.
|
|
503
518
|
request.extra_resources()
|
|
504
519
|
for name, selector in requirements.extra_resources:
|
|
505
520
|
await self.set_required(
|
|
506
|
-
name,
|
|
521
|
+
name,
|
|
522
|
+
selector,
|
|
523
|
+
cast(protobuf.MapMessage, request.extra_resources),
|
|
524
|
+
resources,
|
|
525
|
+
api,
|
|
507
526
|
)
|
|
508
527
|
# Fetch the schemas requested.
|
|
509
528
|
request.required_schemas()
|
|
510
529
|
for name, selector in requirements.schemas:
|
|
511
530
|
await self.set_schema(
|
|
512
|
-
name,
|
|
531
|
+
name,
|
|
532
|
+
selector,
|
|
533
|
+
cast(protobuf.MapMessage, request.required_schemas),
|
|
534
|
+
schemas,
|
|
535
|
+
api,
|
|
513
536
|
)
|
|
514
537
|
# Run the step using the function-pythonic function runner.
|
|
515
538
|
response = protobuf.Message(
|
|
516
539
|
None,
|
|
517
540
|
"response",
|
|
518
541
|
fnv1.RunFunctionResponse.DESCRIPTOR,
|
|
519
|
-
await runner.RunFunction(
|
|
542
|
+
await runner.RunFunction(
|
|
543
|
+
cast(fnv1.RunFunctionRequest, request._message),
|
|
544
|
+
None,
|
|
545
|
+
),
|
|
520
546
|
)
|
|
521
547
|
# Copy the response context to the request context to use in subsequent steps.
|
|
522
548
|
request.context = response.context
|
|
@@ -535,9 +561,14 @@ class Command(command.Command):
|
|
|
535
561
|
|
|
536
562
|
# Copy the response desired state to the request desired state to use in subsequent steps.
|
|
537
563
|
request.desired.resources()
|
|
538
|
-
self.copy_resource(
|
|
564
|
+
self.copy_resource(
|
|
565
|
+
cast(protobuf.Message, response.desired.composite),
|
|
566
|
+
cast(protobuf.Message, request.desired.composite),
|
|
567
|
+
)
|
|
539
568
|
for name, resource in response.desired.resources:
|
|
540
|
-
self.copy_resource(
|
|
569
|
+
self.copy_resource(
|
|
570
|
+
resource, cast(protobuf.Message, request.desired.resources[name])
|
|
571
|
+
)
|
|
541
572
|
|
|
542
573
|
# Collect the step's returned conditions.
|
|
543
574
|
for condition in response.conditions:
|
|
@@ -565,8 +596,8 @@ class Command(command.Command):
|
|
|
565
596
|
break
|
|
566
597
|
|
|
567
598
|
# Collect and format all the returned desired composed resources.
|
|
568
|
-
resources = protobuf.List()
|
|
569
|
-
unready = protobuf.List()
|
|
599
|
+
resources: protobuf.Value = protobuf.List()
|
|
600
|
+
unready: protobuf.Value = protobuf.List()
|
|
570
601
|
prefix = composite.metadata.labels["crossplane.io/composite"]
|
|
571
602
|
if not prefix:
|
|
572
603
|
prefix = composite.metadata.name
|
|
@@ -580,7 +611,9 @@ class Command(command.Command):
|
|
|
580
611
|
if not ready:
|
|
581
612
|
unready[protobuf.append] = name
|
|
582
613
|
resource = resource.resource
|
|
583
|
-
observed =
|
|
614
|
+
observed: protobuf.Value = cast(
|
|
615
|
+
protobuf.Value, request.observed.resources[name].resource
|
|
616
|
+
)
|
|
584
617
|
if observed:
|
|
585
618
|
for key in ("namespace", "generateName", "name"):
|
|
586
619
|
if observed.metadata[key]:
|
|
@@ -666,7 +699,14 @@ class Command(command.Command):
|
|
|
666
699
|
response.observed[name] = resource.resource
|
|
667
700
|
return response
|
|
668
701
|
|
|
669
|
-
async def get_composite_ref(
|
|
702
|
+
async def get_composite_ref(
|
|
703
|
+
self,
|
|
704
|
+
composite: protobuf.Value,
|
|
705
|
+
ref: protobuf.Value,
|
|
706
|
+
request: protobuf.Message,
|
|
707
|
+
resources: list[protobuf.Value],
|
|
708
|
+
api: Api,
|
|
709
|
+
) -> None:
|
|
670
710
|
namespace = ref.namespace
|
|
671
711
|
if not namespace:
|
|
672
712
|
namespace = composite.metadata.namespace
|
|
@@ -680,9 +720,18 @@ class Command(command.Command):
|
|
|
680
720
|
if name:
|
|
681
721
|
destination = request.observed.resources[name]
|
|
682
722
|
if not destination: # Do not override manual observed
|
|
683
|
-
await self.set_resource(
|
|
723
|
+
await self.set_resource(
|
|
724
|
+
source, cast(protobuf.Value, destination), resources, api
|
|
725
|
+
)
|
|
684
726
|
|
|
685
|
-
async def set_required(
|
|
727
|
+
async def set_required(
|
|
728
|
+
self,
|
|
729
|
+
name: protobuf.TypeString,
|
|
730
|
+
selector: protobuf.Message,
|
|
731
|
+
requireds: protobuf.MapMessage,
|
|
732
|
+
resources: list[protobuf.Value] | None = None,
|
|
733
|
+
api: Api | None = None,
|
|
734
|
+
) -> None:
|
|
686
735
|
if resources is None:
|
|
687
736
|
resources = []
|
|
688
737
|
if not name:
|
|
@@ -718,10 +767,10 @@ class Command(command.Command):
|
|
|
718
767
|
if len(selector.match_name):
|
|
719
768
|
resource = await self.kr8s_get(
|
|
720
769
|
api,
|
|
721
|
-
selector.kind,
|
|
722
|
-
selector.api_version,
|
|
723
|
-
selector.namespace,
|
|
724
|
-
selector.match_name,
|
|
770
|
+
cast(protobuf.TypeString, selector.kind),
|
|
771
|
+
cast(protobuf.TypeString, selector.api_version),
|
|
772
|
+
cast(protobuf.TypeString, selector.namespace),
|
|
773
|
+
cast(protobuf.TypeString, selector.match_name),
|
|
725
774
|
)
|
|
726
775
|
if resource:
|
|
727
776
|
await self.set_resource(
|
|
@@ -730,16 +779,41 @@ class Command(command.Command):
|
|
|
730
779
|
elif len(selector.match_labels.labels):
|
|
731
780
|
for resource in await self.kr8s_list(
|
|
732
781
|
api,
|
|
733
|
-
selector.kind,
|
|
734
|
-
selector.api_version,
|
|
735
|
-
selector.namespace,
|
|
736
|
-
selector.match_labels.labels,
|
|
782
|
+
cast(protobuf.TypeString, selector.kind),
|
|
783
|
+
cast(protobuf.TypeString, selector.api_version),
|
|
784
|
+
cast(protobuf.TypeString, selector.namespace),
|
|
785
|
+
cast(protobuf.MapMessage, selector.match_labels.labels),
|
|
737
786
|
):
|
|
738
787
|
await self.set_resource(
|
|
739
788
|
resource, items[protobuf.append], resources, api
|
|
740
789
|
)
|
|
741
790
|
|
|
742
|
-
|
|
791
|
+
def requirement_selector(self, requirement: protobuf.Value) -> protobuf.Message:
|
|
792
|
+
# Convert a Composition step requirement into a function ResourceSelector.
|
|
793
|
+
selector = protobuf.Message(
|
|
794
|
+
None,
|
|
795
|
+
"selector",
|
|
796
|
+
fnv1.ResourceSelector.DESCRIPTOR,
|
|
797
|
+
fnv1.ResourceSelector(),
|
|
798
|
+
)
|
|
799
|
+
selector.api_version = requirement.apiVersion
|
|
800
|
+
selector.kind = requirement.kind
|
|
801
|
+
if requirement.namespace:
|
|
802
|
+
selector.namespace = requirement.namespace
|
|
803
|
+
if requirement.name:
|
|
804
|
+
selector.match_name = requirement.name
|
|
805
|
+
elif requirement.matchLabels:
|
|
806
|
+
for key, value in requirement.matchLabels:
|
|
807
|
+
selector.match_labels.labels[key] = value
|
|
808
|
+
return selector
|
|
809
|
+
|
|
810
|
+
async def set_resource(
|
|
811
|
+
self,
|
|
812
|
+
source: protobuf.Value,
|
|
813
|
+
destination: protobuf.Value,
|
|
814
|
+
resources: list[protobuf.Value] | None = None,
|
|
815
|
+
api: Api | None = None,
|
|
816
|
+
) -> None:
|
|
743
817
|
if resources is None:
|
|
744
818
|
resources = []
|
|
745
819
|
destination.resource = source
|
|
@@ -769,7 +843,14 @@ class Command(command.Command):
|
|
|
769
843
|
for key, value in connection.data:
|
|
770
844
|
destination.connection_details[key] = protobuf.B64Decode(value)
|
|
771
845
|
|
|
772
|
-
async def set_schema(
|
|
846
|
+
async def set_schema(
|
|
847
|
+
self,
|
|
848
|
+
name: protobuf.TypeString,
|
|
849
|
+
selector: protobuf.Value,
|
|
850
|
+
schemas: protobuf.MapMessage,
|
|
851
|
+
documents: list[protobuf.Value] | None = None,
|
|
852
|
+
api: Api | None = None,
|
|
853
|
+
) -> None:
|
|
773
854
|
if documents is None:
|
|
774
855
|
documents = []
|
|
775
856
|
if not name:
|
|
@@ -801,7 +882,9 @@ class Command(command.Command):
|
|
|
801
882
|
return
|
|
802
883
|
self.find_schema(gvk, document, schema)
|
|
803
884
|
|
|
804
|
-
def find_schema(
|
|
885
|
+
def find_schema(
|
|
886
|
+
self, gvk: protobuf.Value, document: protobuf.Value, schema: protobuf.Value
|
|
887
|
+
) -> bool:
|
|
805
888
|
for name, s in document.components.schemas:
|
|
806
889
|
gvks = s["x-kubernetes-group-version-kind"]
|
|
807
890
|
if len(gvks) == 1 and gvks[0] == gvk:
|
|
@@ -811,20 +894,23 @@ class Command(command.Command):
|
|
|
811
894
|
return True
|
|
812
895
|
return False
|
|
813
896
|
|
|
814
|
-
def resolve_ref(
|
|
897
|
+
def resolve_ref(
|
|
898
|
+
self,
|
|
899
|
+
document: protobuf.Value,
|
|
900
|
+
visiting: set,
|
|
901
|
+
ref: protobuf.TypeString,
|
|
902
|
+
schema: protobuf.Value,
|
|
903
|
+
) -> None:
|
|
815
904
|
if not ref:
|
|
816
905
|
return
|
|
817
906
|
ref = str(ref)
|
|
818
907
|
if ref in visiting:
|
|
819
908
|
return
|
|
820
|
-
|
|
821
|
-
for segment in ref.split("/"):
|
|
822
|
-
if segment == "#":
|
|
823
|
-
d = document
|
|
824
|
-
else:
|
|
825
|
-
d = d[segment]
|
|
826
|
-
if not d:
|
|
909
|
+
if not ref.startswith("#/"):
|
|
827
910
|
return
|
|
911
|
+
d = document
|
|
912
|
+
for segment in ref.split("/")[1:]:
|
|
913
|
+
d = d[segment]
|
|
828
914
|
visiting.add(ref)
|
|
829
915
|
try:
|
|
830
916
|
for name, value in d:
|
|
@@ -832,7 +918,14 @@ class Command(command.Command):
|
|
|
832
918
|
finally:
|
|
833
919
|
visiting.remove(ref)
|
|
834
920
|
|
|
835
|
-
def copy_schema(
|
|
921
|
+
def copy_schema(
|
|
922
|
+
self,
|
|
923
|
+
document: protobuf.Value,
|
|
924
|
+
visiting: set,
|
|
925
|
+
key: str | int,
|
|
926
|
+
value: protobuf.Value,
|
|
927
|
+
schema: protobuf.Value,
|
|
928
|
+
) -> None:
|
|
836
929
|
if key == "$ref":
|
|
837
930
|
self.resolve_ref(document, visiting, value, schema)
|
|
838
931
|
elif key == "allOf":
|
|
@@ -850,29 +943,37 @@ class Command(command.Command):
|
|
|
850
943
|
else:
|
|
851
944
|
schema[key] = value
|
|
852
945
|
|
|
853
|
-
def copy_resource(
|
|
946
|
+
def copy_resource(
|
|
947
|
+
self, source: protobuf.Message, destination: protobuf.Message
|
|
948
|
+
) -> None:
|
|
854
949
|
destination.resource = source.resource
|
|
855
950
|
destination.connection_details()
|
|
856
951
|
for key, value in source.connection_details:
|
|
857
952
|
destination.connection_details[key] = value
|
|
858
953
|
destination.ready = source.ready
|
|
859
954
|
|
|
860
|
-
def create_condition(
|
|
955
|
+
def create_condition(
|
|
956
|
+
self,
|
|
957
|
+
type: str,
|
|
958
|
+
status: protobuf.FieldMessage | bool | None,
|
|
959
|
+
reason: str,
|
|
960
|
+
message: str | None = None,
|
|
961
|
+
) -> dict[str, str]:
|
|
861
962
|
if isinstance(status, protobuf.FieldMessage):
|
|
862
963
|
if status._value == fnv1.Status.STATUS_CONDITION_TRUE:
|
|
863
|
-
status = "True"
|
|
964
|
+
status: str = "True"
|
|
864
965
|
elif status._value == fnv1.Status.STATUS_CONDITION_FALSE:
|
|
865
|
-
status = "False"
|
|
966
|
+
status: str = "False"
|
|
866
967
|
else:
|
|
867
|
-
status = "Unknown"
|
|
968
|
+
status: str = "Unknown"
|
|
868
969
|
elif isinstance(status, bool):
|
|
869
970
|
if status:
|
|
870
|
-
status = "True"
|
|
971
|
+
status: str = "True"
|
|
871
972
|
else:
|
|
872
|
-
status = "False"
|
|
973
|
+
status: str = "False"
|
|
873
974
|
elif status is None:
|
|
874
|
-
status = "Unknown"
|
|
875
|
-
condition = {
|
|
975
|
+
status: str = "Unknown"
|
|
976
|
+
condition: dict[str, str] = {
|
|
876
977
|
"type": type,
|
|
877
978
|
"status": status,
|
|
878
979
|
"reason": reason,
|
|
@@ -882,8 +983,15 @@ class Command(command.Command):
|
|
|
882
983
|
condition["message"] = message
|
|
883
984
|
return condition
|
|
884
985
|
|
|
885
|
-
async def kr8s_get(
|
|
886
|
-
|
|
986
|
+
async def kr8s_get(
|
|
987
|
+
self,
|
|
988
|
+
api: Api,
|
|
989
|
+
kind: protobuf.TypeString,
|
|
990
|
+
apiVersion: protobuf.TypeString,
|
|
991
|
+
namespace: protobuf.TypeString | None,
|
|
992
|
+
name: protobuf.TypeString,
|
|
993
|
+
) -> protobuf.Value | None:
|
|
994
|
+
namespaced = bool(namespace) and bool(len(namespace))
|
|
887
995
|
clazz = self.kr8s_class(kind, apiVersion, namespaced)
|
|
888
996
|
try:
|
|
889
997
|
fullName = [str(kind), str(apiVersion), str(name)]
|
|
@@ -900,15 +1008,27 @@ class Command(command.Command):
|
|
|
900
1008
|
self.logger.debug(f"Resource {result}: {':'.join(fullName)}")
|
|
901
1009
|
return resource
|
|
902
1010
|
|
|
903
|
-
async def kr8s_list(
|
|
904
|
-
|
|
1011
|
+
async def kr8s_list(
|
|
1012
|
+
self,
|
|
1013
|
+
api: Api,
|
|
1014
|
+
kind: protobuf.TypeString,
|
|
1015
|
+
apiVersion: protobuf.TypeString,
|
|
1016
|
+
namespace: protobuf.TypeString | None,
|
|
1017
|
+
labelSelector: protobuf.MapMessage,
|
|
1018
|
+
) -> list[protobuf.Value]:
|
|
1019
|
+
namespaced = bool(namespace) and bool(len(namespace))
|
|
905
1020
|
clazz = self.kr8s_class(kind, apiVersion, namespaced)
|
|
906
1021
|
resources = [
|
|
907
1022
|
protobuf.Value(None, None, resource.raw)
|
|
908
|
-
async for resource in
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
1023
|
+
async for resource in cast(
|
|
1024
|
+
typing.AsyncGenerator[kr8s.APIObject],
|
|
1025
|
+
clazz.list(
|
|
1026
|
+
namespace=str(namespace) if namespaced else None,
|
|
1027
|
+
label_selector={
|
|
1028
|
+
label: str(value) for label, value in labelSelector
|
|
1029
|
+
},
|
|
1030
|
+
api=api,
|
|
1031
|
+
),
|
|
912
1032
|
)
|
|
913
1033
|
]
|
|
914
1034
|
if self.logger.isEnabledFor(logging.DEBUG):
|
|
@@ -919,13 +1039,18 @@ class Command(command.Command):
|
|
|
919
1039
|
"&".join(f"{label}={value}" for label, value in labelSelector)
|
|
920
1040
|
)
|
|
921
1041
|
if resources:
|
|
922
|
-
result = f"found {INFLECT.number_to_words(len(resources))}"
|
|
1042
|
+
result = f"found {INFLECT.number_to_words(str(len(resources)))}"
|
|
923
1043
|
else:
|
|
924
1044
|
result = "missing"
|
|
925
1045
|
self.logger.debug(f"Resources {result}: {':'.join(fullName)}")
|
|
926
1046
|
return resources
|
|
927
1047
|
|
|
928
|
-
def kr8s_class(
|
|
1048
|
+
def kr8s_class(
|
|
1049
|
+
self,
|
|
1050
|
+
kind: protobuf.TypeString,
|
|
1051
|
+
apiVersion: protobuf.TypeString,
|
|
1052
|
+
namespaced: bool,
|
|
1053
|
+
) -> type[kr8s.APIObject]:
|
|
929
1054
|
try:
|
|
930
1055
|
return kr8s.asyncio.objects.get_class(str(kind), str(apiVersion), True)
|
|
931
1056
|
except KeyError:
|
crossplane/pythonic/version.py
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: crossplane-function-pythonic
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: A Python centric Crossplane Function
|
|
5
5
|
Author: Patrick J McNerthney
|
|
6
6
|
Author-email: Patrick J McNerthney <pat@mcnerthney.com>
|
|
7
7
|
License-Expression: Apache-2.0
|
|
8
|
-
Requires-Dist: grpcio==1.
|
|
8
|
+
Requires-Dist: grpcio==1.85.1
|
|
9
9
|
Requires-Dist: inflect==7.6.0
|
|
10
10
|
Requires-Dist: kr8s==0.20.15
|
|
11
11
|
Requires-Dist: protobuf==7.36.2
|
|
12
12
|
Requires-Dist: pyyaml==6.0.3
|
|
13
|
-
Requires-Dist: kopf==1.45.
|
|
13
|
+
Requires-Dist: kopf==1.45.2 ; extra == 'packages'
|
|
14
14
|
Requires-Dist: pip==26.2.2 ; extra == 'pip-install'
|
|
15
|
-
Requires-Python: >=3.
|
|
15
|
+
Requires-Python: >=3.15, <3.16
|
|
16
16
|
Project-URL: Documentation, https://github.com/crossplane-contrib/function-pythonic#readme
|
|
17
17
|
Project-URL: Issues, https://github.com/crossplane-contrib/function-pythonic/issues
|
|
18
18
|
Project-URL: Source, https://github.com/crossplane-contrib/function-pythonic
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
crossplane/pythonic/__about__.py,sha256=xViFFR_npzf2RXvljN98CNoUFOZ2KN9Hwgcbx4KCPpg,180
|
|
2
|
+
crossplane/pythonic/__init__.py,sha256=b4LHrCWoibhkzeIAWbXsT_JBW4S2X7twrA7c1BtMxAo,331
|
|
3
|
+
crossplane/pythonic/__main__.py,sha256=Ipm-KZJB7V1CFJ96iF1-pN8CBfK7qdsykjsmt4hl7LQ,32
|
|
4
|
+
crossplane/pythonic/auto_ready.py,sha256=n9hnv6f2vzCHFr-Lq_CAib5ik5vVxpORSQIUE1lOoVE,8153
|
|
5
|
+
crossplane/pythonic/command.py,sha256=vPx8zqg4NpIsZsECa75r6wFJse_g__jsPvspe9-5TXE,4691
|
|
6
|
+
crossplane/pythonic/composite.py,sha256=xg4ntzYJL-FfVsgQL452cy8yMB0NWv90VNAAk5WWZLU,45249
|
|
7
|
+
crossplane/pythonic/function.py,sha256=qRhr_QBuSucUZvjGrzEL92a3kH3z-BTyNp9Q0SBF6q4,22624
|
|
8
|
+
crossplane/pythonic/grpc.py,sha256=iQ5NUxnzvQ5zMgjNdjERiml2KpJHi9tgqd5Ez-xterc,6115
|
|
9
|
+
crossplane/pythonic/main.py,sha256=fa3mwEaULscAF2IszvIkLf7l-ryP3hElnlpJZXUhaM0,981
|
|
10
|
+
crossplane/pythonic/packages.py,sha256=8UIPuGz8xiCuDoNyuN-kcJIyjPQkcPyTQd1Gfdmz7CM,7855
|
|
11
|
+
crossplane/pythonic/proto/v1/run_function.proto,sha256=GbJ0wVUEjfpMsn2DsnhiPvtmL09z3oyMbWwf6viQtiw,16676
|
|
12
|
+
crossplane/pythonic/proto/v1/run_function_pb2.py,sha256=kj1vcbOGGMlnF0YxMR774JhTQsfIk0Y5ZRRBpF_F5nY,14440
|
|
13
|
+
crossplane/pythonic/proto/v1/run_function_pb2.pyi,sha256=eFq00EFNSY3Pj_6CUJR90qa_kc82uZ2Y3jSw8CVIWoQ,53056
|
|
14
|
+
crossplane/pythonic/proto/v1/run_function_pb2_grpc.py,sha256=VOIGzcYAbgJgXUPEg1iMZY4LJ27E448nfwQxxIVS5ag,3944
|
|
15
|
+
crossplane/pythonic/proto/v1/run_function_pb2_grpc.pyi,sha256=QQsbwTUlzW36c75ujlrgZMa3Zk8xalTpWm4q5oE2qWc,2406
|
|
16
|
+
crossplane/pythonic/protobuf.py,sha256=6IJGpo9WCEg9WVzYY0QV3h5Go2wk2pinEFruimV_a0g,61006
|
|
17
|
+
crossplane/pythonic/render.py,sha256=OUHrTBU3qFMiliXljnsdJ48yF9M1mI0sRW_plBlyoWo,42247
|
|
18
|
+
crossplane/pythonic/version.py,sha256=T70dXiH5zW7qhQ2Tigw4xBT-zBVDwm5Sp1BEmQ4SQrw,221
|
|
19
|
+
crossplane_function_pythonic-0.7.0.dist-info/WHEEL,sha256=3NO1oYsF7mANFUWVdyEQLM-zmecczWWEmmF5rEbXrWk,80
|
|
20
|
+
crossplane_function_pythonic-0.7.0.dist-info/entry_points.txt,sha256=yT7OSM0ZYJoX1rya2HZfIrGzCXbYdqMblBtqEDH8LzM,69
|
|
21
|
+
crossplane_function_pythonic-0.7.0.dist-info/METADATA,sha256=KDlgGfoLqVHwB_xXn4sHoJXnY5Vp2VJeQRM6hpFRD0E,36502
|
|
22
|
+
crossplane_function_pythonic-0.7.0.dist-info/RECORD,,
|