crossplane-function-sdk-python 0.12.0__tar.gz → 0.13.0__tar.gz

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.
Files changed (44) hide show
  1. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/PKG-INFO +3 -3
  2. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/__version__.py +1 -1
  3. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/resource.py +18 -8
  4. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/pyproject.toml +2 -2
  5. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/tests/test_resource.py +197 -6
  6. crossplane_function_sdk_python-0.13.0/tests/testdata/models/io/k8s/api/__init__.py +2 -0
  7. crossplane_function_sdk_python-0.13.0/tests/testdata/models/io/k8s/api/resource/__init__.py +2 -0
  8. crossplane_function_sdk_python-0.13.0/tests/testdata/models/io/k8s/api/resource/v1.py +66 -0
  9. crossplane_function_sdk_python-0.13.0/tests/testdata/models/io/upbound/m/__init__.py +0 -0
  10. crossplane_function_sdk_python-0.13.0/tests/testdata/models/io/upbound/m/aws/__init__.py +0 -0
  11. crossplane_function_sdk_python-0.13.0/tests/testdata/models/io/upbound/m/aws/iam/__init__.py +0 -0
  12. crossplane_function_sdk_python-0.13.0/tests/testdata/models/io/upbound/m/aws/iam/accountalias/__init__.py +0 -0
  13. crossplane_function_sdk_python-0.13.0/tests/testdata/models/io/upbound/m/aws/iam/accountalias/v1beta1.py +166 -0
  14. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  15. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  16. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  17. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/.github/workflows/ci.yml +0 -0
  18. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/.gitignore +0 -0
  19. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/CODEOWNERS +0 -0
  20. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/LICENSE +0 -0
  21. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/OWNERS.md +0 -0
  22. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/README.md +0 -0
  23. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/logging.py +0 -0
  24. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/proto/v1/run_function.proto +0 -0
  25. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/proto/v1/run_function_pb2.py +0 -0
  26. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/proto/v1/run_function_pb2.pyi +0 -0
  27. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/proto/v1/run_function_pb2_grpc.py +0 -0
  28. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/proto/v1beta1/run_function.proto +0 -0
  29. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/proto/v1beta1/run_function_pb2.py +0 -0
  30. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/proto/v1beta1/run_function_pb2.pyi +0 -0
  31. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/proto/v1beta1/run_function_pb2_grpc.py +0 -0
  32. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/py.typed +0 -0
  33. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/request.py +0 -0
  34. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/response.py +0 -0
  35. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/crossplane/function/runtime.py +0 -0
  36. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/renovate.json +0 -0
  37. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/tests/test_request.py +0 -0
  38. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/tests/test_response.py +0 -0
  39. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/tests/test_runtime.py +0 -0
  40. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/tests/testdata/models/io/k8s/apimachinery/pkg/apis/__init__.py +0 -0
  41. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/tests/testdata/models/io/k8s/apimachinery/pkg/apis/meta/__init__.py +0 -0
  42. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/tests/testdata/models/io/k8s/apimachinery/pkg/apis/meta/v1.py +0 -0
  43. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/tests/testdata/models/io/upbound/aws/s3/__init__.py +0 -0
  44. {crossplane_function_sdk_python-0.12.0 → crossplane_function_sdk_python-0.13.0}/tests/testdata/models/io/upbound/aws/s3/v1beta2.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crossplane-function-sdk-python
3
- Version: 0.12.0
3
+ Version: 0.13.0
4
4
  Summary: The Python SDK for Crossplane composition functions
5
5
  Project-URL: Documentation, https://github.com/crossplane/function-sdk-python#readme
6
6
  Project-URL: Issues, https://github.com/crossplane/function-sdk-python/issues
@@ -14,10 +14,10 @@ Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Typing :: Typed
15
15
  Requires-Python: >=3.11
16
16
  Requires-Dist: grpcio-reflection==1.*
17
- Requires-Dist: grpcio==1.80.0
17
+ Requires-Dist: grpcio==1.81.0
18
18
  Requires-Dist: protobuf==7.35.0
19
19
  Requires-Dist: pydantic==2.*
20
- Requires-Dist: structlog==25.*
20
+ Requires-Dist: structlog==26.*
21
21
  Description-Content-Type: text/markdown
22
22
 
23
23
  # function-sdk-python
@@ -15,4 +15,4 @@
15
15
  """The version of function-sdk-python."""
16
16
 
17
17
  # This is set at build time, using "hatch version"
18
- __version__ = "0.12.0"
18
+ __version__ = "0.13.0"
@@ -40,12 +40,21 @@ def update(r: fnv1.Resource, source: dict | structpb.Struct | pydantic.BaseModel
40
40
  """
41
41
  match source:
42
42
  case pydantic.BaseModel():
43
- data = source.model_dump(exclude_defaults=True, warnings=False)
44
- # In Pydantic, exclude_defaults=True in model_dump excludes fields
45
- # that have their value equal to the default. If a field like
46
- # apiVersion is set to its default value 's3.aws.upbound.io/v1beta2'
47
- # (and not explicitly provided during initialization), it will be
48
- # excluded from the serialized output.
43
+ # exclude_unset emits only the fields the caller explicitly set.
44
+ # Crossplane treats desired resources as server-side apply intent,
45
+ # so a function should own exactly the fields it has an opinion
46
+ # about and leave the rest to the API server.
47
+ #
48
+ # by_alias emits each field under its alias, which is its real
49
+ # wire name. datamodel-code-generator aliases fields whose KRM
50
+ # name collides with a Python keyword or builtin (e.g. it emits a
51
+ # bool_ attribute aliased to bool, continue_ aliased to continue).
52
+ # Without by_alias those fields serialize under the Python name and
53
+ # don't match the resource's schema. It's a no-op for ordinary
54
+ # fields, which have no alias.
55
+ data = source.model_dump(exclude_unset=True, by_alias=True, warnings=False)
56
+ # apiVersion and kind identify the resource but are rarely passed
57
+ # as kwargs, so they're usually unset. Add them back explicitly.
49
58
  data["apiVersion"] = source.apiVersion
50
59
  data["kind"] = source.kind
51
60
  r.resource.update(data)
@@ -71,11 +80,12 @@ def update_status(
71
80
  status: The status to set, as a dictionary or Pydantic model.
72
81
 
73
82
  Sets ``r.resource.status`` from the supplied status. When the status
74
- is a Pydantic model, fields set to their default value are excluded,
83
+ is a Pydantic model, fields the caller didn't explicitly set are
84
+ excluded and aliased fields are emitted under their wire names,
75
85
  matching the behavior of :func:`update`.
76
86
  """
77
87
  if isinstance(status, pydantic.BaseModel):
78
- status = status.model_dump(exclude_defaults=True, warnings=False)
88
+ status = status.model_dump(exclude_unset=True, by_alias=True, warnings=False)
79
89
  update(r, {"status": status})
80
90
 
81
91
 
@@ -18,11 +18,11 @@ classifiers = [
18
18
  ]
19
19
 
20
20
  dependencies = [
21
- "grpcio==1.80.0",
21
+ "grpcio==1.81.0",
22
22
  "grpcio-reflection==1.*",
23
23
  "protobuf==7.35.0", # Must be compatible with grpcio-tools.
24
24
  "pydantic==2.*",
25
- "structlog==25.*",
25
+ "structlog==26.*",
26
26
  ]
27
27
 
28
28
  dynamic = ["version"]
@@ -22,7 +22,11 @@ from google.protobuf import struct_pb2 as structpb
22
22
 
23
23
  import crossplane.function.proto.v1.run_function_pb2 as fnv1
24
24
  from crossplane.function import logging, resource
25
- from tests.testdata.models.io.upbound.aws.s3 import v1beta2
25
+ from tests.testdata.models.io.k8s.api.resource import v1 as resourcev1
26
+ from tests.testdata.models.io.upbound.aws.s3 import v1beta2 as s3v1beta2
27
+ from tests.testdata.models.io.upbound.m.aws.iam.accountalias import (
28
+ v1beta1 as accountaliasv1beta1,
29
+ )
26
30
 
27
31
 
28
32
  class TestResource(unittest.TestCase):
@@ -59,13 +63,43 @@ class TestResource(unittest.TestCase):
59
63
  {"apiVersion": "example.org", "kind": "XR"}
60
64
  ),
61
65
  ),
62
- status=v1beta2.ForProvider(region="us-west-2"),
66
+ status=s3v1beta2.ForProvider(region="us-west-2"),
63
67
  want={
64
68
  "apiVersion": "example.org",
65
69
  "kind": "XR",
66
70
  "status": {"region": "us-west-2"},
67
71
  },
68
72
  ),
73
+ TestCase(
74
+ reason="Fields the caller set should be kept, while unset "
75
+ "fields are omitted.",
76
+ r=fnv1.Resource(
77
+ resource=resource.dict_to_struct(
78
+ {"apiVersion": "example.org", "kind": "XR"}
79
+ ),
80
+ ),
81
+ status=s3v1beta2.ForProvider(region="us-west-2", forceDestroy=False),
82
+ want={
83
+ "apiVersion": "example.org",
84
+ "kind": "XR",
85
+ "status": {"region": "us-west-2", "forceDestroy": False},
86
+ },
87
+ ),
88
+ TestCase(
89
+ reason="Setting status from a Pydantic model with keyword-"
90
+ "aliased fields should emit the fields under their aliases.",
91
+ r=fnv1.Resource(
92
+ resource=resource.dict_to_struct(
93
+ {"apiVersion": "example.org", "kind": "XR"}
94
+ ),
95
+ ),
96
+ status=resourcev1.DeviceAttribute(**{"bool": True}),
97
+ want={
98
+ "apiVersion": "example.org",
99
+ "kind": "XR",
100
+ "status": {"bool": True},
101
+ },
102
+ ),
69
103
  TestCase(
70
104
  reason="Setting status on an empty resource should work.",
71
105
  r=fnv1.Resource(),
@@ -131,11 +165,16 @@ class TestResource(unittest.TestCase):
131
165
  ),
132
166
  ),
133
167
  TestCase(
134
- reason="Updating from a Pydantic model should work.",
168
+ # This model uses the default_factory form that older
169
+ # datamodel-code-generator emits for fields with an object
170
+ # default. providerConfigRef has such a default but isn't set
171
+ # here, so it must not be emitted.
172
+ reason="Updating from a Pydantic model with default_factory "
173
+ "object defaults should omit unset fields.",
135
174
  r=fnv1.Resource(),
136
- source=v1beta2.Bucket(
137
- spec=v1beta2.Spec(
138
- forProvider=v1beta2.ForProvider(region="us-west-2"),
175
+ source=s3v1beta2.Bucket(
176
+ spec=s3v1beta2.Spec(
177
+ forProvider=s3v1beta2.ForProvider(region="us-west-2"),
139
178
  ),
140
179
  ),
141
180
  want=fnv1.Resource(
@@ -148,6 +187,98 @@ class TestResource(unittest.TestCase):
148
187
  ),
149
188
  ),
150
189
  ),
190
+ TestCase(
191
+ # This model uses the validate_default=True form that newer
192
+ # datamodel-code-generator emits for fields with an object
193
+ # default. providerConfigRef has such a default but isn't set
194
+ # here, so it must not be emitted.
195
+ reason="Updating from a Pydantic model with validate_default "
196
+ "object defaults should omit unset fields.",
197
+ r=fnv1.Resource(),
198
+ source=accountaliasv1beta1.AccountAlias(
199
+ spec=accountaliasv1beta1.Spec(forProvider={"x": "y"}),
200
+ ),
201
+ want=fnv1.Resource(
202
+ resource=resource.dict_to_struct(
203
+ {
204
+ "apiVersion": "iam.aws.m.upbound.io/v1beta1",
205
+ "kind": "AccountAlias",
206
+ "spec": {"forProvider": {"x": "y"}},
207
+ }
208
+ ),
209
+ ),
210
+ ),
211
+ TestCase(
212
+ # datamodel-code-generator can't name a field bool or int, so
213
+ # it emits bool_ aliased to bool and int_ aliased to int. The
214
+ # alias is the resource's real wire name, so update must emit
215
+ # fields under their aliases.
216
+ reason="Updating from a Pydantic model with keyword-aliased "
217
+ "fields should emit the fields under their aliases.",
218
+ r=fnv1.Resource(),
219
+ source=resourcev1.ResourceSlice(
220
+ spec=resourcev1.Spec(
221
+ devices=[
222
+ resourcev1.Device(
223
+ name="gpu",
224
+ attributes={
225
+ "powered": resourcev1.DeviceAttribute(
226
+ **{"bool": True},
227
+ ),
228
+ "lanes": resourcev1.DeviceAttribute(
229
+ **{"int": 16},
230
+ ),
231
+ },
232
+ ),
233
+ ],
234
+ ),
235
+ ),
236
+ want=fnv1.Resource(
237
+ resource=resource.dict_to_struct(
238
+ {
239
+ "apiVersion": "resource.k8s.io/v1",
240
+ "kind": "ResourceSlice",
241
+ "spec": {
242
+ "devices": [
243
+ {
244
+ "name": "gpu",
245
+ "attributes": {
246
+ "powered": {"bool": True},
247
+ "lanes": {"int": 16},
248
+ },
249
+ },
250
+ ],
251
+ },
252
+ }
253
+ ),
254
+ ),
255
+ ),
256
+ TestCase(
257
+ # managementPolicies defaults to ["*"] and is set to ["*"]
258
+ # here. A field the caller sets is one it has an opinion about
259
+ # and should own, even when the value equals the default.
260
+ reason="A field the caller explicitly set to its default value "
261
+ "should be emitted.",
262
+ r=fnv1.Resource(),
263
+ source=accountaliasv1beta1.AccountAlias(
264
+ spec=accountaliasv1beta1.Spec(
265
+ forProvider={"x": "y"},
266
+ managementPolicies=["*"],
267
+ ),
268
+ ),
269
+ want=fnv1.Resource(
270
+ resource=resource.dict_to_struct(
271
+ {
272
+ "apiVersion": "iam.aws.m.upbound.io/v1beta1",
273
+ "kind": "AccountAlias",
274
+ "spec": {
275
+ "forProvider": {"x": "y"},
276
+ "managementPolicies": ["*"],
277
+ },
278
+ }
279
+ ),
280
+ ),
281
+ ),
151
282
  ]
152
283
 
153
284
  for case in cases:
@@ -158,6 +289,66 @@ class TestResource(unittest.TestCase):
158
289
  "-want, +got",
159
290
  )
160
291
 
292
+ def test_model_round_trip(self) -> None:
293
+ # A function reads an observed resource (wire names), validates it into
294
+ # a model, then writes it back via update. A field that goes in under
295
+ # its wire name must come back out under the same wire name. This pins
296
+ # the property the by_alias fix exists to guarantee: validation accepts
297
+ # the alias, and serialization must emit the alias, not the Python
298
+ # attribute name. It does not assert anything about fields the model
299
+ # doesn't define (pydantic drops them) or value types (Struct coerces
300
+ # numbers to float).
301
+ @dataclasses.dataclass
302
+ class TestCase:
303
+ reason: str
304
+ # The resource as it arrives from Crossplane, using wire names.
305
+ observed: dict
306
+ # The model type to validate the observed resource into.
307
+ model: type[pydantic.BaseModel]
308
+
309
+ cases = [
310
+ TestCase(
311
+ reason="A model with keyword-aliased fields should round-trip "
312
+ "through validation and update with its fields under the same "
313
+ "wire names (bool, int) they arrived under.",
314
+ observed={
315
+ "apiVersion": "resource.k8s.io/v1",
316
+ "kind": "ResourceSlice",
317
+ "spec": {
318
+ "devices": [
319
+ {
320
+ "name": "gpu",
321
+ "attributes": {
322
+ "powered": {"bool": True},
323
+ "lanes": {"int": 16},
324
+ "model": {"string": "h100"},
325
+ },
326
+ },
327
+ ],
328
+ },
329
+ },
330
+ model=resourcev1.ResourceSlice,
331
+ ),
332
+ TestCase(
333
+ reason="A model with only ordinary fields should round-trip unchanged.",
334
+ observed={
335
+ "apiVersion": "s3.aws.upbound.io/v1beta2",
336
+ "kind": "Bucket",
337
+ "spec": {"forProvider": {"region": "us-west-2"}},
338
+ },
339
+ model=s3v1beta2.Bucket,
340
+ ),
341
+ ]
342
+
343
+ for case in cases:
344
+ # Mimic the SDK flow: a function reads an observed resource (wire
345
+ # names), validates it into a model, then writes it back out.
346
+ m = case.model.model_validate(case.observed)
347
+ r = fnv1.Resource()
348
+ resource.update(r, m)
349
+ got = resource.struct_to_dict(r.resource)
350
+ self.assertEqual(case.observed, got, case.reason)
351
+
161
352
  def test_get_condition(self) -> None:
162
353
  @dataclasses.dataclass
163
354
  class TestCase:
@@ -0,0 +1,2 @@
1
+ # generated by datamodel-codegen:
2
+ # filename: <stdin>
@@ -0,0 +1,2 @@
1
+ # generated by datamodel-codegen:
2
+ # filename: <stdin>
@@ -0,0 +1,66 @@
1
+ # generated by datamodel-codegen:
2
+ # filename: <stdin>
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import Literal
7
+
8
+ from pydantic import BaseModel, Field
9
+
10
+ from ...apimachinery.pkg.apis.meta import v1
11
+
12
+
13
+ class DeviceAttribute(BaseModel):
14
+ bool_: bool | None = Field(None, alias='bool')
15
+ """
16
+ BoolValue is a true/false value.
17
+ """
18
+ int_: int | None = Field(None, alias='int')
19
+ """
20
+ IntValue is a number.
21
+ """
22
+ string: str | None = None
23
+ """
24
+ StringValue is a string.
25
+ """
26
+ version: str | None = None
27
+ """
28
+ VersionValue is a semantic version according to semver.org spec 2.0.0.
29
+ """
30
+
31
+
32
+ class Device(BaseModel):
33
+ name: str
34
+ """
35
+ Name is a unique identifier among all devices managed by the driver.
36
+ """
37
+ attributes: dict[str, DeviceAttribute] | None = None
38
+ """
39
+ Attributes defines the set of attributes for this device.
40
+ """
41
+
42
+
43
+ class Spec(BaseModel):
44
+ devices: list[Device] | None = None
45
+ """
46
+ Devices lists the devices in this resource slice.
47
+ """
48
+
49
+
50
+ class ResourceSlice(BaseModel):
51
+ apiVersion: Literal['resource.k8s.io/v1'] | None = 'resource.k8s.io/v1'
52
+ """
53
+ APIVersion defines the versioned schema of this representation of an object.
54
+ """
55
+ kind: Literal['ResourceSlice'] | None = 'ResourceSlice'
56
+ """
57
+ Kind is a string value representing the REST resource this object represents.
58
+ """
59
+ metadata: v1.ObjectMeta | None = None
60
+ """
61
+ Standard object's metadata.
62
+ """
63
+ spec: Spec
64
+ """
65
+ Contents of the ResourceSlice.
66
+ """
@@ -0,0 +1,166 @@
1
+ # generated by datamodel-codegen:
2
+ # filename: workdir/iam_aws_m_upbound_io_v1beta1_accountalias.yaml
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import Any, Literal
7
+
8
+ from pydantic import AwareDatetime, BaseModel, Field
9
+
10
+ from ......k8s.apimachinery.pkg.apis.meta import v1
11
+
12
+
13
+ class ProviderConfigRef(BaseModel):
14
+ kind: str
15
+ """
16
+ Kind of the referenced object.
17
+ """
18
+ name: str
19
+ """
20
+ Name of the referenced object.
21
+ """
22
+
23
+
24
+ class WriteConnectionSecretToRef(BaseModel):
25
+ name: str
26
+ """
27
+ Name of the secret.
28
+ """
29
+
30
+
31
+ class Spec(BaseModel):
32
+ forProvider: dict[str, Any]
33
+ initProvider: dict[str, Any] | None = None
34
+ """
35
+ THIS IS A BETA FIELD. It will be honored
36
+ unless the Management Policies feature flag is disabled.
37
+ InitProvider holds the same fields as ForProvider, with the exception
38
+ of Identifier and other resource reference fields. The fields that are
39
+ in InitProvider are merged into ForProvider when the resource is created.
40
+ The same fields are also added to the terraform ignore_changes hook, to
41
+ avoid updating them after creation. This is useful for fields that are
42
+ required on creation, but we do not desire to update them after creation,
43
+ for example because of an external controller is managing them, like an
44
+ autoscaler.
45
+ """
46
+ managementPolicies: (
47
+ list[Literal['Observe', 'Create', 'Update', 'Delete', 'LateInitialize', '*']]
48
+ | None
49
+ ) = ['*']
50
+ """
51
+ THIS IS A BETA FIELD. It is on by default but can be opted out
52
+ through a Crossplane feature flag.
53
+ ManagementPolicies specify the array of actions Crossplane is allowed to
54
+ take on the managed and external resources.
55
+ See the design doc for more information: https://github.com/crossplane/crossplane/blob/499895a25d1a1a0ba1604944ef98ac7a1a71f197/design/design-doc-observe-only-resources.md?plain=1#L223
56
+ and this one: https://github.com/crossplane/crossplane/blob/444267e84783136daa93568b364a5f01228cacbe/design/one-pager-ignore-changes.md
57
+ """
58
+ providerConfigRef: ProviderConfigRef | None = Field(
59
+ {'kind': 'ClusterProviderConfig', 'name': 'default'}, validate_default=True
60
+ )
61
+ """
62
+ ProviderConfigReference specifies how the provider that will be used to
63
+ create, observe, update, and delete this managed resource should be
64
+ configured.
65
+ """
66
+ writeConnectionSecretToRef: WriteConnectionSecretToRef | None = None
67
+ """
68
+ WriteConnectionSecretToReference specifies the namespace and name of a
69
+ Secret to which any connection details for this managed resource should
70
+ be written. Connection details frequently include the endpoint, username,
71
+ and password required to connect to the managed resource.
72
+ """
73
+
74
+
75
+ class AtProvider(BaseModel):
76
+ id: str | None = None
77
+
78
+
79
+ class Condition(BaseModel):
80
+ lastTransitionTime: AwareDatetime
81
+ """
82
+ LastTransitionTime is the last time this condition transitioned from one
83
+ status to another.
84
+ """
85
+ message: str | None = None
86
+ """
87
+ A Message containing details about this condition's last transition from
88
+ one status to another, if any.
89
+ """
90
+ observedGeneration: int | None = None
91
+ """
92
+ ObservedGeneration represents the .metadata.generation that the condition was set based upon.
93
+ For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
94
+ with respect to the current state of the instance.
95
+ """
96
+ reason: str
97
+ """
98
+ A Reason for this condition's last transition from one status to another.
99
+ """
100
+ status: str
101
+ """
102
+ Status of this condition; is it currently True, False, or Unknown?
103
+ """
104
+ type: str
105
+ """
106
+ Type of this condition. At most one of each condition type may apply to
107
+ a resource at any point in time.
108
+ """
109
+
110
+
111
+ class Status(BaseModel):
112
+ atProvider: AtProvider | None = None
113
+ conditions: list[Condition] | None = None
114
+ """
115
+ Conditions of the resource.
116
+ """
117
+ observedGeneration: int | None = None
118
+ """
119
+ ObservedGeneration is the latest metadata.generation
120
+ which resulted in either a ready state, or stalled due to error
121
+ it can not recover from without human intervention.
122
+ """
123
+
124
+
125
+ class AccountAlias(BaseModel):
126
+ apiVersion: Literal['iam.aws.m.upbound.io/v1beta1'] | None = (
127
+ 'iam.aws.m.upbound.io/v1beta1'
128
+ )
129
+ """
130
+ APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
131
+ """
132
+ kind: Literal['AccountAlias'] | None = 'AccountAlias'
133
+ """
134
+ Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
135
+ """
136
+ metadata: v1.ObjectMeta | None = None
137
+ """
138
+ Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
139
+ """
140
+ spec: Spec
141
+ """
142
+ AccountAliasSpec defines the desired state of AccountAlias
143
+ """
144
+ status: Status | None = None
145
+ """
146
+ AccountAliasStatus defines the observed state of AccountAlias.
147
+ """
148
+
149
+
150
+ class AccountAliasList(BaseModel):
151
+ apiVersion: str | None = None
152
+ """
153
+ APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
154
+ """
155
+ items: list[AccountAlias]
156
+ """
157
+ List of accountaliases. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md
158
+ """
159
+ kind: str | None = None
160
+ """
161
+ Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
162
+ """
163
+ metadata: v1.ListMeta | None = None
164
+ """
165
+ Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
166
+ """