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/__about__.py
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
from importlib.metadata import PackageNotFoundError, version
|
|
2
2
|
|
|
3
3
|
try:
|
|
4
|
-
__version__ = version(
|
|
5
|
-
"crossplane-function-pythonic"
|
|
6
|
-
) # Use the exact [project.name] from pyproject.toml
|
|
4
|
+
__version__ = version("crossplane-function-pythonic")
|
|
7
5
|
except PackageNotFoundError:
|
|
8
6
|
__version__ = "0.0.0"
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from . import (
|
|
5
|
+
composite,
|
|
6
|
+
protobuf,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def resource_ready(resource: composite.Resource) -> protobuf.Value | None:
|
|
2
11
|
if not resource.observed:
|
|
3
12
|
return None
|
|
4
13
|
return _checks.get(
|
|
@@ -7,9 +16,9 @@ def resource_ready(resource):
|
|
|
7
16
|
|
|
8
17
|
|
|
9
18
|
class ReadyCondition:
|
|
10
|
-
def ready(self, resource):
|
|
19
|
+
def ready(self, resource: composite.Resource) -> protobuf.Value | None:
|
|
11
20
|
ready = resource.conditions.Ready
|
|
12
|
-
if not ready.
|
|
21
|
+
if not ready._get_condition():
|
|
13
22
|
return None
|
|
14
23
|
if ready.status:
|
|
15
24
|
return resource.observed.metadata.name
|
|
@@ -18,7 +27,7 @@ class ReadyCondition:
|
|
|
18
27
|
return resource.status.notReadyCondition
|
|
19
28
|
|
|
20
29
|
|
|
21
|
-
_checks = {}
|
|
30
|
+
_checks: dict[tuple, Check] = {}
|
|
22
31
|
_check_default = ReadyCondition()
|
|
23
32
|
|
|
24
33
|
|
|
@@ -29,12 +38,12 @@ class Check:
|
|
|
29
38
|
if hasattr(cls, "apiVersion"):
|
|
30
39
|
_checks[(cls.apiVersion, cls.__name__)] = cls()
|
|
31
40
|
|
|
32
|
-
def ready(self, resource):
|
|
41
|
+
def ready(self, resource: composite.Resource) -> protobuf.Value | None:
|
|
33
42
|
raise NotImplementedError()
|
|
34
43
|
|
|
35
44
|
|
|
36
45
|
class AlwaysReady(Check):
|
|
37
|
-
def ready(self, resource):
|
|
46
|
+
def ready(self, resource: composite.Resource) -> protobuf.Value:
|
|
38
47
|
return resource.observed.metadata.name
|
|
39
48
|
|
|
40
49
|
|
|
@@ -53,7 +62,7 @@ class ConfigMap(AlwaysReady):
|
|
|
53
62
|
class CronJob(Check):
|
|
54
63
|
apiVersion = "batch/v1"
|
|
55
64
|
|
|
56
|
-
def ready(self, resource):
|
|
65
|
+
def ready(self, resource: composite.Resource) -> protobuf.Value:
|
|
57
66
|
if resource.observed.spec.suspend and len(resource.observed.spec.suspend):
|
|
58
67
|
return resource.observed.metadata.name
|
|
59
68
|
if not resource.status.lastScheduleTime:
|
|
@@ -72,7 +81,7 @@ class CronJob(Check):
|
|
|
72
81
|
class DaemonSet(Check):
|
|
73
82
|
apiVersion = "apps/v1"
|
|
74
83
|
|
|
75
|
-
def ready(self, resource):
|
|
84
|
+
def ready(self, resource: composite.Resource) -> protobuf.Value:
|
|
76
85
|
scheduled = resource.status.desiredNumberScheduled
|
|
77
86
|
if not scheduled:
|
|
78
87
|
return scheduled
|
|
@@ -88,7 +97,7 @@ class DaemonSet(Check):
|
|
|
88
97
|
class Deployment(Check):
|
|
89
98
|
apiVersion = "apps/v1"
|
|
90
99
|
|
|
91
|
-
def ready(self, resource):
|
|
100
|
+
def ready(self, resource: composite.Resource) -> protobuf.Value:
|
|
92
101
|
replicas = resource.observed.spec.replicas or 1
|
|
93
102
|
for field in ("updatedReplicas", "availableReplicas"):
|
|
94
103
|
value = resource.status[field]
|
|
@@ -109,7 +118,7 @@ class Deployment(Check):
|
|
|
109
118
|
class HorizontalPodAutoscaler(Check):
|
|
110
119
|
apiVersion = "autoscaling/v2"
|
|
111
120
|
|
|
112
|
-
def ready(self, resource):
|
|
121
|
+
def ready(self, resource: composite.Resource) -> protobuf.Value:
|
|
113
122
|
for type in (
|
|
114
123
|
"FailedGetScale",
|
|
115
124
|
"FailedUpdateScale",
|
|
@@ -121,22 +130,22 @@ class HorizontalPodAutoscaler(Check):
|
|
|
121
130
|
for type in ("ScalingActive", "ScalingLimited"):
|
|
122
131
|
if resource.conditions[type].status:
|
|
123
132
|
return resource.observed.metadata.name
|
|
124
|
-
return resource.status.
|
|
133
|
+
return resource.status.notScalingActiveOrLimited
|
|
125
134
|
|
|
126
135
|
|
|
127
136
|
class Ingress(Check):
|
|
128
137
|
apiVersion = "networking.k8s.io/v1"
|
|
129
138
|
|
|
130
|
-
def ready(self, resource):
|
|
139
|
+
def ready(self, resource: composite.Resource) -> protobuf.Value:
|
|
131
140
|
if not len(resource.status.loadBalancer.ingress):
|
|
132
|
-
return resource.status.
|
|
141
|
+
return resource.status.noLoadBalancerIngresses
|
|
133
142
|
return resource.observed.metadata.name
|
|
134
143
|
|
|
135
144
|
|
|
136
145
|
class Job(Check):
|
|
137
146
|
apiVersion = "batch/v1"
|
|
138
147
|
|
|
139
|
-
def ready(self, resource):
|
|
148
|
+
def ready(self, resource: composite.Resource) -> protobuf.Value:
|
|
140
149
|
for type in ("Failed", "Suspended"):
|
|
141
150
|
if resource.conditions[type].status:
|
|
142
151
|
return resource.status[f"is{type}"]
|
|
@@ -157,7 +166,7 @@ class Namespace(AlwaysReady):
|
|
|
157
166
|
class PersistentVolumeClaim(Check):
|
|
158
167
|
apiVersion = "v1"
|
|
159
168
|
|
|
160
|
-
def ready(self, resource):
|
|
169
|
+
def ready(self, resource: composite.Resource) -> protobuf.Value:
|
|
161
170
|
if resource.status.phase != "Bound":
|
|
162
171
|
return resource.status.phaseNotBound
|
|
163
172
|
return resource.observed.metadata.name
|
|
@@ -166,7 +175,7 @@ class PersistentVolumeClaim(Check):
|
|
|
166
175
|
class Pod(Check):
|
|
167
176
|
apiVersion = "v1"
|
|
168
177
|
|
|
169
|
-
def ready(self, resource):
|
|
178
|
+
def ready(self, resource: composite.Resource) -> protobuf.Value:
|
|
170
179
|
if resource.status.phase == "Succeeded":
|
|
171
180
|
return resource.observed.metadata.name
|
|
172
181
|
if (
|
|
@@ -179,9 +188,9 @@ class Pod(Check):
|
|
|
179
188
|
|
|
180
189
|
|
|
181
190
|
class ReplicaSet(Check):
|
|
182
|
-
apiVersion = "v1"
|
|
191
|
+
apiVersion = "apps/v1"
|
|
183
192
|
|
|
184
|
-
def ready(self, resource):
|
|
193
|
+
def ready(self, resource: composite.Resource) -> protobuf.Value:
|
|
185
194
|
if int(resource.status.observedGeneration) < int(
|
|
186
195
|
resource.observed.metadata.generation
|
|
187
196
|
):
|
|
@@ -195,7 +204,7 @@ class ReplicaSet(Check):
|
|
|
195
204
|
if int(resource.status.availableReplicas) < int(
|
|
196
205
|
resource.observed.spec.replicas or 1
|
|
197
206
|
):
|
|
198
|
-
return resource.status.
|
|
207
|
+
return resource.status.tooFewAvailableReplicas
|
|
199
208
|
return resource.observed.metadata.name
|
|
200
209
|
|
|
201
210
|
|
|
@@ -214,7 +223,7 @@ class Secret(AlwaysReady):
|
|
|
214
223
|
class Service(Check):
|
|
215
224
|
apiVersion = "v1"
|
|
216
225
|
|
|
217
|
-
def ready(self, resource):
|
|
226
|
+
def ready(self, resource: composite.Resource) -> protobuf.Value:
|
|
218
227
|
if resource.observed.spec.type != "LoadBalancer":
|
|
219
228
|
return resource.observed.metadata.name
|
|
220
229
|
if not len(resource.status.loadBalancer.ingress):
|
|
@@ -229,7 +238,7 @@ class ServiceAccount(AlwaysReady):
|
|
|
229
238
|
class StatefulSet(Check):
|
|
230
239
|
apiVersion = "apps/v1"
|
|
231
240
|
|
|
232
|
-
def ready(self, resource):
|
|
241
|
+
def ready(self, resource: composite.Resource) -> protobuf.Value:
|
|
233
242
|
replicas = resource.observed.spec.replicas or 1
|
|
234
243
|
for field in ("readyReplicas", "currentReplicas"):
|
|
235
244
|
value = resource.status[field]
|
|
@@ -238,5 +247,5 @@ class StatefulSet(Check):
|
|
|
238
247
|
if replicas != value:
|
|
239
248
|
return resource.status[f"{field}NotReplicas"]
|
|
240
249
|
if resource.status.currentRevision != resource.status.updateRevision:
|
|
241
|
-
return resource.status.
|
|
250
|
+
return resource.status.currentRevisionNotUpdateRevision
|
|
242
251
|
return resource.observed.metadata.name
|
crossplane/pythonic/command.py
CHANGED
|
@@ -1,27 +1,32 @@
|
|
|
1
|
+
import argparse
|
|
1
2
|
import logging
|
|
2
3
|
import pathlib
|
|
3
4
|
import sys
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class Command:
|
|
7
|
-
name = None
|
|
8
|
-
command = None
|
|
9
|
-
|
|
8
|
+
name: str | None = None
|
|
9
|
+
command: str | None = None
|
|
10
|
+
help: str | None = None
|
|
11
|
+
description: str | None = None
|
|
10
12
|
|
|
11
13
|
@classmethod
|
|
12
|
-
def create(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
def create(
|
|
15
|
+
cls, subparsers: argparse._SubParsersAction[argparse.ArgumentParser]
|
|
16
|
+
) -> None:
|
|
17
|
+
if cls.name is not None:
|
|
18
|
+
parser: argparse.ArgumentParser = subparsers.add_parser(
|
|
19
|
+
cls.name, help=cls.help, description=cls.description
|
|
20
|
+
)
|
|
21
|
+
parser.set_defaults(command=cls)
|
|
22
|
+
cls.add_parser_arguments(parser)
|
|
18
23
|
|
|
19
24
|
@classmethod
|
|
20
|
-
def add_parser_arguments(cls, parser):
|
|
25
|
+
def add_parser_arguments(cls, parser: argparse.ArgumentParser) -> None:
|
|
21
26
|
pass
|
|
22
27
|
|
|
23
28
|
@classmethod
|
|
24
|
-
def add_function_arguments(cls, parser):
|
|
29
|
+
def add_function_arguments(cls, parser: argparse.ArgumentParser) -> None:
|
|
25
30
|
parser.add_argument(
|
|
26
31
|
"--debug",
|
|
27
32
|
"-d",
|
|
@@ -66,14 +71,14 @@ class Command:
|
|
|
66
71
|
help="Enable Crossplane V1 compatibility mode",
|
|
67
72
|
)
|
|
68
73
|
|
|
69
|
-
def __init__(self, args=None):
|
|
70
|
-
self.args = args
|
|
74
|
+
def __init__(self, args: argparse.Namespace | None = None) -> None:
|
|
75
|
+
self.args = args if args is not None else argparse.Namespace()
|
|
71
76
|
self.initialize()
|
|
72
77
|
|
|
73
|
-
def initialize(self):
|
|
78
|
+
def initialize(self) -> None:
|
|
74
79
|
pass
|
|
75
80
|
|
|
76
|
-
def initialize_function(self):
|
|
81
|
+
def initialize_function(self) -> None:
|
|
77
82
|
formatter = Formatter(self.args.log_name_width)
|
|
78
83
|
handler = logging.StreamHandler(sys.stdout)
|
|
79
84
|
handler.setFormatter(formatter)
|
|
@@ -98,15 +103,16 @@ class Command:
|
|
|
98
103
|
if self.args.allow_oversize_protos:
|
|
99
104
|
from google.protobuf.internal import api_implementation
|
|
100
105
|
|
|
101
|
-
|
|
102
|
-
|
|
106
|
+
c_module = getattr(api_implementation, "_c_module", None)
|
|
107
|
+
if c_module:
|
|
108
|
+
c_module.SetAllowOversizeProtos(True)
|
|
103
109
|
|
|
104
|
-
async def run(self):
|
|
110
|
+
async def run(self) -> None:
|
|
105
111
|
raise NotImplementedError()
|
|
106
112
|
|
|
107
113
|
|
|
108
114
|
class Formatter(logging.Formatter):
|
|
109
|
-
def __init__(self, name_width):
|
|
115
|
+
def __init__(self, name_width: int):
|
|
110
116
|
super().__init__(
|
|
111
117
|
f"[{{asctime}}.{{msecs:03.0f}}] {{sname:{name_width}.{name_width}}} [{{levelname:8.8}}] {{message}}",
|
|
112
118
|
"%Y-%m-%d %H:%M:%S",
|
|
@@ -114,16 +120,17 @@ class Formatter(logging.Formatter):
|
|
|
114
120
|
)
|
|
115
121
|
self.name_width = name_width
|
|
116
122
|
|
|
117
|
-
def format(self, record):
|
|
118
|
-
|
|
119
|
-
extra = len(
|
|
123
|
+
def format(self, record: logging.LogRecord):
|
|
124
|
+
sname = record.name
|
|
125
|
+
extra = len(sname) - self.name_width
|
|
120
126
|
if extra > 0:
|
|
121
|
-
names =
|
|
127
|
+
names = sname.split(".")
|
|
122
128
|
for ix, name in enumerate(names):
|
|
123
129
|
if len(name) > extra:
|
|
124
130
|
names[ix] = name[extra:]
|
|
125
131
|
break
|
|
126
132
|
names[ix] = name[:1]
|
|
127
133
|
extra -= len(name) - 1
|
|
128
|
-
|
|
134
|
+
sname = ".".join(names)
|
|
135
|
+
record.sname = sname
|
|
129
136
|
return super().format(record)
|