Skip to content

Commit d7d9ff7

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

10 files changed

Lines changed: 446 additions & 235 deletions

File tree

README.md

Lines changed: 4 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,9 @@ 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 |
285284
| Resource.usages | Boolean | Generate Crossplane Usages for this resource, default is Composite.autoReady |
286285
| Resource.autoReady | Boolean | Perform auto ready processing on this resource, default is Composite.autoReady |
286+
| Resource.unknownsFatal | Boolean | Terminate the composition if this resource has been created and is assigned unknown values, default is Composite.unknownsFatal |
287287

288288
### Required Resources
289289

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: 63 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,22 +332,26 @@ 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
346+
347+
def setConditionReady(self):
348+
if self.conditions.Ready.status:
349+
self.ready = self.observed.metadata.name
350+
else:
351+
if self.conditions.Ready.reason:
352+
self.ready = self.status.notReady[self.conditions.Ready.reason]
353+
else:
354+
self.ready = self.status.notReady
337355

338356

339357
class Requireds:
@@ -408,12 +426,18 @@ def __init__(self, composite, name):
408426
self._resources = composite.request.required_resources[name]
409427
self._cache = {}
410428

411-
def __call__(self, apiVersion=_notset, kind=_notset, namespace=_notset, name=_notset, labels=_notset):
429+
def __call__(self, kind=_notset, apiVersion=_notset, namespace=_notset, name=_notset, labels=_notset):
412430
self._selector()
431+
if kind != _notset:
432+
# Allow for apiVersion in the first arg and kind in the second arg
433+
if '/' in kind or kind == 'v1':
434+
if apiVersion != _notset:
435+
self.kind = apiVersion
436+
apiVersion = kind
437+
else:
438+
self.kind = kind
413439
if apiVersion != _notset:
414440
self.apiVersion = apiVersion
415-
if kind != _notset:
416-
self.kind = kind
417441
if namespace != _notset:
418442
self.namespace = namespace
419443
if name != _notset:
@@ -802,60 +826,36 @@ def _resource_name(self):
802826

803827
@property
804828
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
829+
return self._composite.response.observed.composite.connection_details
811830

812831
def __getattr__(self, key):
813832
return self[key]
814833

815834
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
835+
return self._composite.response.desired.composite.connection_details[key]
822836

823837
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)
838+
return bool(self._composite.response.desired.composite.connection_details)
827839

828840
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)
841+
return len(self._composite.response.desired.composite.connection_details)
832842

833843
def __contains__(self, key):
834-
if self._composite.crossplane_v1:
835-
return key in self._composite.response.desired.composite.connection_details
844+
return key in self._composite.response.desired.composite.connection_details
836845

837846
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)
847+
for key, value in self._composite.response.desired.composite.connection_details:
848+
yield key, value
844849

845850
def __str__(self):
846851
return format(self)
847852

848853
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)
854+
return format(self._composite.response.desired.composite.connection_details, spec)
855855

856856
def __call__(self, **kwargs):
857+
self._composite.response.desired.composite.connection_details(**kwargs)
857858
if self._composite_v1:
858-
self._composite.response.desired.composite.connection_details(**kwargs)
859859
return
860860
del self._composite.resources[self._resource_name]
861861
for key, value in kwargs:
@@ -872,16 +872,13 @@ def __setitem__(self, key, value):
872872
if not value:
873873
return
874874
value = str(value)
875-
if self._composite.crossplane_v1:
876-
self._composite.response.desired.composite.connection_details[key] = value
875+
self._composite.response.desired.composite.connection_details[key] = value
876+
if self._composite.crossplane_v1 or not self._composite.connectionSecret.name:
877877
return
878-
#if not self._composite.connectionSecret.name:
879-
# return
880878
if self._resource_name in self._composite.resources:
881879
secret = self._composite.resources[self._resource_name]
882880
else:
883881
secret = self._composite.resources[self._resource_name]('v1', 'Secret')
884-
print(bool(self._composite.connectionSecret.name), len(self._composite.connectionSecret.name))
885882
if self._composite.connectionSecret.name and len(self._composite.connectionSecret.name):
886883
secret.metadata.name = self._composite.connectionSecret.name
887884
if not self._composite.metadata.namespace:
@@ -896,8 +893,8 @@ def __delattr__(self, key):
896893
del self[key]
897894

898895
def __delitem__(self, key):
896+
del self._composite.response.desired.composite.connection_details[key]
899897
if self._composite.crossplane_v1:
900-
del self._composite.response.desired.composite.connection_details[key]
901898
return
902899
if self._resource_name in self._composite.resources:
903900
del self._composite.resources[self._resource_name].data[key]

crossplane/pythonic/protobuf.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,29 @@ def Unknown():
3737

3838
def Yaml(string, readOnly=None):
3939
if isinstance(string, (FieldMessage, Value)):
40+
if not string:
41+
return string
4042
string = str(string)
4143
return Value(None, None, yaml.safe_load(string), readOnly)
4244

4345
def Json(string, readOnly=None):
4446
if isinstance(string, (FieldMessage, Value)):
47+
if not string:
48+
return string
4549
string = str(string)
4650
return Value(None, None, json.loads(string), readOnly)
4751

4852
def B64Encode(string):
4953
if isinstance(string, (FieldMessage, Value)):
54+
if not string:
55+
return string
5056
string = str(string)
5157
return base64.b64encode(string.encode('utf-8')).decode('utf-8')
5258

5359
def B64Decode(string):
5460
if isinstance(string, (FieldMessage, Value)):
61+
if not string:
62+
return string
5563
string = str(string)
5664
return base64.b64decode(string.encode('utf-8')).decode('utf-8')
5765

@@ -684,10 +692,11 @@ def __getattr__(self, key):
684692

685693
def __getitem__(self, key):
686694
key = self._validate_key(key)
687-
if key in self._cache:
688-
return self._cache[key]
689-
if key in self._unknowns:
690-
return self._unknowns[key]
695+
if key != append:
696+
if key in self._cache:
697+
return self._cache[key]
698+
if key in self._unknowns:
699+
return self._unknowns[key]
691700
if isinstance(key, str):
692701
match self._kind:
693702
case 'struct_value':
@@ -701,14 +710,26 @@ def __getitem__(self, key):
701710
elif isinstance(key, int):
702711
match self._kind:
703712
case 'list_value':
713+
if key < 0:
714+
key = len(self._value.list_value.values) + key
715+
if key < 0:
716+
key = 0
704717
if key < len(self._value.list_value.values):
705718
value = self._value.list_value.values[key]
706719
else:
720+
if key == append:
721+
key = len(self._value.list_value.values)
707722
value = _Unknown
708723
case 'ListValue':
724+
if key < 0:
725+
key = len(self._value.values) + key
726+
if key < 0:
727+
key = 0
709728
if key < len(self._value.values):
710729
value = self._value.values[key]
711730
else:
731+
if key == append:
732+
key = len(self._value.values)
712733
value = _Unknown
713734
case 'Unknown':
714735
value = _Unknown

0 commit comments

Comments
 (0)