Skip to content

Commit 18b41a0

Browse files
renovate[bot]iciclespider
authored andcommitted
Integrate render command with an active cluster
1 parent 4f53ce9 commit 18b41a0

10 files changed

Lines changed: 476 additions & 235 deletions

File tree

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,8 @@ The BaseComposite class provides the following fields for manipulating the Compo
236236
| self.conditions | Conditions | The composite desired and observed conditions, read from observed if not in desired |
237237
| self.results | Results | Returned results applied to the Composite and optionally on the Claim |
238238
| self.connectionSecret | Map | The name, namespace, and resourceName to use when generating the connection secret in Crossplane v2 |
239-
| self.connection | Map | The composite desired connection detials |
240-
| self.connection.observed | Map | The composite observed connection detials |
239+
| self.connection | Map | The composite desired connection details |
240+
| self.connection.observed | Map | The composite observed connection details |
241241
| self.ready | Boolean | The composite desired ready state |
242242

243243
The BaseComposite also provides access to the following Crossplane Function level features:
@@ -254,9 +254,9 @@ The BaseComposite also provides access to the following Crossplane Function leve
254254
| self.environment | Map | The response environment, initialized from the request context environment |
255255
| self.requireds | Requireds | Request and read additional local Kubernetes resources |
256256
| self.resources | Resources | Define and process composed resources |
257-
| self.unknownsFatal | Boolean | Terminate the composition if already created resources are assigned unknown values, default True |
258257
| self.usages| Boolean | Generate Crossplane Usages for resource dependencies, default False |
259258
| self.autoReady | Boolean | Perform auto ready processing on all composed resources, default True |
259+
| self.unknownsFatal | Boolean | Terminate the composition if already created resources are assigned unknown values, default False |
260260

261261
### Composed Resources
262262

@@ -281,9 +281,10 @@ Resource class:
281281
| Resource.conditions | Conditions | The resource conditions |
282282
| Resource.connection | Map | The resource observed connection details |
283283
| Resource.ready | Boolean | The resource ready state |
284-
| Resource.unknownsFatal | Boolean | Terminate the composition if this resource has been created and is assigned unknown values, default is Composite.unknownsFatal |
284+
| Resource.setReadyCondition | Method | Set Resource.ready to the Ready Condition status |
285285
| Resource.usages | Boolean | Generate Crossplane Usages for this resource, default is Composite.autoReady |
286286
| Resource.autoReady | Boolean | Perform auto ready processing on this resource, default is Composite.autoReady |
287+
| Resource.unknownsFatal | Boolean | Terminate the composition if this resource has been created and is assigned unknown values, default is Composite.unknownsFatal |
287288

288289
### Required Resources
289290

crossplane/pythonic/auto_ready.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
def process(composite):
44
for name, resource in composite.resources:
5-
if resource.observed:
6-
if resource.autoReady or (resource.autoReady is None and composite.autoReady):
5+
if resource.autoReady or (resource.autoReady is None and composite.autoReady):
6+
if resource.observed:
77
if resource.ready is None:
8-
if _checks.get((resource.apiVersion, resource.kind), _check_default).ready(resource):
8+
if _checks.get((resource.observed.apiVersion, resource.observed.kind), _check_default).ready(resource):
99
resource.ready = True
1010

1111

crossplane/pythonic/command.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ def add_function_arguments(cls, parser):
3333
metavar='WIDTH',
3434
help='Width of the logger name in the log output, default 40.',
3535
)
36+
parser.add_argument(
37+
'--logger-level',
38+
action='append',
39+
default=[],
40+
metavar='LOGGER=LEVEL',
41+
help='Logger level, for example: botocore.hooks=INFO',
42+
)
3643
parser.add_argument(
3744
'--python-path',
3845
action='append',
@@ -70,6 +77,11 @@ def initialize_function(self):
7077
logger = logging.getLogger()
7178
logger.handlers = [handler]
7279
logger.setLevel(logging.DEBUG if self.args.debug else logging.INFO)
80+
for logger_level in self.args.logger_level:
81+
for logger_level in logger_level.split(','):
82+
logger_level = logger_level.split('=')
83+
if len(logger_level) == 2:
84+
logging.getLogger(logger_level[0]).setLevel(logger_level[1].upper())
7385

7486
for path in reversed(self.args.python_path):
7587
sys.path.insert(0, str(pathlib.Path(path).expanduser().resolve()))

crossplane/pythonic/composite.py

Lines changed: 80 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -69,21 +69,22 @@ def __set__(self, composite, ttl):
6969

7070
class Ready:
7171
def __get__(self, composite, objtype=None):
72-
ready = composite.desired._parent.ready
73-
if ready == fnv1.Ready.READY_TRUE:
72+
if hasattr(composite, '_ready'):
73+
return composite._ready
74+
if composite.desired._parent.ready == fnv1.Ready.READY_TRUE:
7475
return True
75-
if ready == fnv1.Ready.READY_FALSE:
76+
if composite.desired._parent.ready == fnv1.Ready.READY_FALSE:
7677
return False
7778
return None
7879

7980
def __set__(self, composite, ready):
81+
composite._ready = ready
8082
if ready:
81-
ready = fnv1.Ready.READY_TRUE
82-
elif ready == None or (isinstance(ready, protobuf.Value) and ready._isUnknown):
83-
ready = fnv1.Ready.READY_UNSPECIFIED
83+
composite.desired._parent.ready = fnv1.Ready.READY_TRUE
84+
elif ready is None:
85+
composite.desired._parent.ready = fnv1.Ready.READY_UNSPECIFIED
8486
else:
85-
ready = fnv1.Ready.READY_FALSE
86-
composite.desired._parent.ready = ready
87+
composite.desired._parent.ready = fnv1.Ready.READY_FALSE
8788

8889

8990
class BaseComposite:
@@ -111,9 +112,9 @@ def __init__(self, crossplane_v1, request, single_use, logger):
111112
self.environment = self.context['apiextensions.crossplane.io/environment']
112113
self.requireds = Requireds(self)
113114
self.resources = Resources(self)
114-
self.unknownsFatal = True
115115
self.autoReady = True
116116
self.usages = False
117+
self.unknownsFatal = False
117118

118119
observed = self.request.observed.composite
119120
desired = self.response.desired.composite
@@ -238,16 +239,28 @@ def __init__(self, composite, name):
238239
self.desired = desired.resource
239240
self.conditions = Conditions(observed)
240241
self.connection = observed.connection_details
241-
self.unknownsFatal = None
242+
if self.desired._parent.ready == fnv1.Ready.READY_TRUE:
243+
self._ready = True
244+
elif self.desired._parent.ready == fnv1.Ready.READY_FALSE:
245+
self._ready = False
246+
else:
247+
self._ready = None
242248
self.autoReady = None
243249
self.usages = None
250+
self.unknownsFatal = None
244251

245-
def __call__(self, apiVersion=_notset, kind=_notset, namespace=_notset, name=_notset):
252+
def __call__(self, kind=_notset, apiVersion=_notset, namespace=_notset, name=_notset):
246253
self.desired()
254+
if kind != _notset:
255+
# Allow for apiVersion in the first arg and kind in the second arg
256+
if '/' in kind or kind == 'v1':
257+
if apiVersion != _notset:
258+
self.kind = apiVersion
259+
apiVersion = kind
260+
else:
261+
self.kind = kind
247262
if apiVersion != _notset:
248263
self.apiVersion = apiVersion
249-
if kind != _notset:
250-
self.kind = kind
251264
if namespace != _notset:
252265
self.metadata.namespace = namespace
253266
if name != _notset:
@@ -296,6 +309,7 @@ def spec(self):
296309
def spec(self, spec):
297310
self.desired.spec = spec
298311

312+
# Used by Secret:v1
299313
@property
300314
def type(self):
301315
return self.desired.type
@@ -318,23 +332,44 @@ def status(self):
318332

319333
@property
320334
def ready(self):
321-
ready = self.desired._parent.ready
322-
if ready == fnv1.Ready.READY_TRUE:
323-
return True
324-
if ready == fnv1.Ready.READY_FALSE:
325-
return False
326-
return None
335+
return self._ready
327336

328337
@ready.setter
329338
def ready(self, ready):
339+
self._ready = ready
330340
if ready:
331-
ready = fnv1.Ready.READY_TRUE
332-
elif ready == None or (isinstance(ready, protobuf.Value) and ready._isUnknown):
333-
ready = fnv1.Ready.READY_UNSPECIFIED
341+
self.desired._parent.ready = fnv1.Ready.READY_TRUE
342+
elif ready is None:
343+
self.desired._parent.ready = fnv1.Ready.READY_UNSPECIFIED
334344
else:
335-
ready = fnv1.Ready.READY_FALSE
336-
self.desired._parent.ready = ready
345+
self.desired._parent.ready = fnv1.Ready.READY_FALSE
337346

347+
def setReadyCondition(self, type='Ready'):
348+
condition = self.conditions[type]
349+
if condition.status:
350+
if condition.reason:
351+
self.ready = condition._find_condition().reason
352+
else:
353+
self.ready = condition._find_condition().type
354+
else:
355+
error = f"not{type}"
356+
if condition.reason:
357+
self.ready = self.status[error][condition.reason]
358+
else:
359+
self.ready = self.status[error]
360+
361+
def addDependency(self, resource, field=None):
362+
if field is None:
363+
field = resource.ready
364+
if not isinstance(field, (protobuf.FieldMessage, protobuf.Value)):
365+
if field:
366+
field = resource.observed.metadata.name
367+
else:
368+
if not resource.observed.metadata.name:
369+
field = resource.observed.metadata.name
370+
else:
371+
field = resource.status.notReady
372+
self.metadata.annotations[f"{resource.name}Ready"] = field
338373

339374
class Requireds:
340375
def __init__(self, composite):
@@ -408,12 +443,18 @@ def __init__(self, composite, name):
408443
self._resources = composite.request.required_resources[name]
409444
self._cache = {}
410445

411-
def __call__(self, apiVersion=_notset, kind=_notset, namespace=_notset, name=_notset, labels=_notset):
446+
def __call__(self, kind=_notset, apiVersion=_notset, namespace=_notset, name=_notset, labels=_notset):
412447
self._selector()
448+
if kind != _notset:
449+
# Allow for apiVersion in the first arg and kind in the second arg
450+
if '/' in kind or kind == 'v1':
451+
if apiVersion != _notset:
452+
self.kind = apiVersion
453+
apiVersion = kind
454+
else:
455+
self.kind = kind
413456
if apiVersion != _notset:
414457
self.apiVersion = apiVersion
415-
if kind != _notset:
416-
self.kind = kind
417458
if namespace != _notset:
418459
self.namespace = namespace
419460
if name != _notset:
@@ -802,60 +843,36 @@ def _resource_name(self):
802843

803844
@property
804845
def observed(self):
805-
if self._composite.crossplane_v1:
806-
return self._composite.response.observed.composite.connection_details
807-
data = protobuf.Map()
808-
for key, value in self._composite.resources[self._resource_name].observed.data:
809-
data[key] = protobuf.B64Decode(value)
810-
return data
846+
return self._composite.response.observed.composite.connection_details
811847

812848
def __getattr__(self, key):
813849
return self[key]
814850

815851
def __getitem__(self, key):
816-
if self._composite.crossplane_v1:
817-
return self._composite.response.desired.composite.connection_details[key]
818-
value = self._composite.resources[self._resource_name].data[key]
819-
if value:
820-
value = protobuf.B64Decode(value)
821-
return value
852+
return self._composite.response.desired.composite.connection_details[key]
822853

823854
def __bool__(self):
824-
if self._composite.crossplane_v1:
825-
return bool(self._composite.response.desired.composite.connection_details)
826-
return bool(self._composite.resources[self._resource_name].data)
855+
return bool(self._composite.response.desired.composite.connection_details)
827856

828857
def __len__(self):
829-
if self._composite.crossplane_v1:
830-
return len(self._composite.response.desired.composite.connection_details)
831-
return len(self._composite.resources[self._resource_name].data)
858+
return len(self._composite.response.desired.composite.connection_details)
832859

833860
def __contains__(self, key):
834-
if self._composite.crossplane_v1:
835-
return key in self._composite.response.desired.composite.connection_details
861+
return key in self._composite.response.desired.composite.connection_details
836862

837863
def __iter__(self):
838-
keys = set()
839-
if self._composite.crossplane_v1:
840-
for key, value in self._composite.response.desired.composite.connection_details:
841-
yield key, value
842-
for key, value in self._composite.resources[self._resource_name].data:
843-
yield key, protobuf.B64Decode(value)
864+
for key, value in self._composite.response.desired.composite.connection_details:
865+
yield key, value
844866

845867
def __str__(self):
846868
return format(self)
847869

848870
def __format__(self, spec='yaml'):
849-
if self._composite.crossplane_v1:
850-
return format(self._composite.response.desired.composite.connection_details, spec)
851-
data = protobuf.Map()
852-
for key, value in self._composite.resources[self._resource_name].data:
853-
data[key] = protobuf.B64Decode(value)
854-
return format(data, spec)
871+
return format(self._composite.response.desired.composite.connection_details, spec)
855872

856873
def __call__(self, **kwargs):
874+
self._composite.response.desired.composite.connection_details(**kwargs)
857875
if self._composite_v1:
858-
self._composite.response.desired.composite.connection_details(**kwargs)
859876
return
860877
del self._composite.resources[self._resource_name]
861878
for key, value in kwargs:
@@ -872,16 +889,13 @@ def __setitem__(self, key, value):
872889
if not value:
873890
return
874891
value = str(value)
875-
if self._composite.crossplane_v1:
876-
self._composite.response.desired.composite.connection_details[key] = value
892+
self._composite.response.desired.composite.connection_details[key] = value
893+
if self._composite.crossplane_v1 or not self._composite.connectionSecret.name:
877894
return
878-
#if not self._composite.connectionSecret.name:
879-
# return
880895
if self._resource_name in self._composite.resources:
881896
secret = self._composite.resources[self._resource_name]
882897
else:
883898
secret = self._composite.resources[self._resource_name]('v1', 'Secret')
884-
print(bool(self._composite.connectionSecret.name), len(self._composite.connectionSecret.name))
885899
if self._composite.connectionSecret.name and len(self._composite.connectionSecret.name):
886900
secret.metadata.name = self._composite.connectionSecret.name
887901
if not self._composite.metadata.namespace:
@@ -896,8 +910,8 @@ def __delattr__(self, key):
896910
del self[key]
897911

898912
def __delitem__(self, key):
913+
del self._composite.response.desired.composite.connection_details[key]
899914
if self._composite.crossplane_v1:
900-
del self._composite.response.desired.composite.connection_details[key]
901915
return
902916
if self._resource_name in self._composite.resources:
903917
del self._composite.resources[self._resource_name].data[key]

0 commit comments

Comments
 (0)