crossplane-function-pythonic 0.3.0__py3-none-any.whl → 0.4.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.
@@ -1,2 +1,2 @@
1
1
  # This is set at build time, using "hatch version"
2
- __version__ = "0.3.0"
2
+ __version__ = "0.4.0"
@@ -1,20 +1,23 @@
1
1
 
2
+ def resource_ready(resource):
3
+ if not resource.observed:
4
+ return None
5
+ return _checks.get((resource.observed.apiVersion, resource.observed.kind), _check_default).ready(resource)
2
6
 
3
- def process(composite):
4
- for name, resource in composite.resources:
5
- if resource.observed:
6
- if resource.autoReady or (resource.autoReady is None and composite.autoReady):
7
- if resource.ready is None:
8
- if _checks.get((resource.apiVersion, resource.kind), _check_default).ready(resource):
9
- resource.ready = True
10
7
 
11
-
12
- class ConditionReady:
8
+ class ReadyCondition:
13
9
  def ready(self, resource):
14
- return bool(resource.conditions.Ready.status)
10
+ ready = resource.conditions.Ready
11
+ if not ready._find_condition():
12
+ return None
13
+ if ready.status:
14
+ return resource.observed.metadata.name
15
+ if ready.reason:
16
+ return resource.status.notReadyCondition[ready.reason]
17
+ return resource.status.notReadyCondition
15
18
 
16
19
  _checks = {}
17
- _check_default = ConditionReady()
20
+ _check_default = ReadyCondition()
18
21
 
19
22
  class Check:
20
23
  @classmethod
@@ -28,7 +31,7 @@ class Check:
28
31
 
29
32
  class AlwaysReady(Check):
30
33
  def ready(self, resource):
31
- return True
34
+ return resource.observed.metadata.name
32
35
 
33
36
 
34
37
  class ClusterRole(AlwaysReady):
@@ -44,57 +47,82 @@ class CronJob(Check):
44
47
  apiVersion = 'batch/v1'
45
48
  def ready(self, resource):
46
49
  if resource.observed.spec.suspend and len(resource.observed.spec.suspend):
47
- return True
50
+ return resource.observed.metadata.name
48
51
  if not resource.status.lastScheduleTime:
49
- return False
52
+ return resource.status.lastScheduleTime
50
53
  if resource.status.active:
51
- return True
54
+ return resource.observed.metadata.name
52
55
  if not resource.status.lastSuccessfulTime:
53
- return False
54
- return str(resource.status.lastSuccessfulTime) >= str(resource.status.lastScheduleTime)
56
+ return resource.status.lastSuccessfulTime
57
+ if str(resource.status.lastSuccessfulTime) < str(resource.status.lastScheduleTime):
58
+ return resource.status.successfulBeforeSchedule
59
+ return resource.observed.metadata.name
55
60
 
56
61
  class DaemonSet(Check):
57
62
  apiVersion = 'apps/v1'
58
63
  def ready(self, resource):
59
- if not resource.status.desiredNumberScheduled:
60
- return False
61
64
  scheduled = resource.status.desiredNumberScheduled
62
- return (scheduled == resource.status.numberReady and
63
- scheduled == resource.status.updatedNumberScheduled and
64
- scheduled == resource.status.numberAvailable
65
- )
65
+ if not scheduled:
66
+ return scheduled
67
+ for field in ('numberReady', 'updatedNumberScheduled', 'numberAvailable'):
68
+ value = resource.status[field]
69
+ if not value:
70
+ return value
71
+ if scheduled != value:
72
+ return resource.status[f"{field}NotScheduled"]
73
+ return resource.observed.metadata.name
66
74
 
67
75
  class Deployment(Check):
68
76
  apiVersion = 'apps/v1'
69
77
  def ready(self, resource):
70
78
  replicas = resource.observed.spec.replicas or 1
71
- if resource.status.updatedReplicas != replicas or resource.status.availableReplicas != replicas:
72
- return False
73
- return bool(resource.conditions.Available.status)
79
+ for field in ('updatedReplicas', 'availableReplicas'):
80
+ value = resource.status[field]
81
+ if not value:
82
+ return value
83
+ if replicas != value:
84
+ return resource.status[F"{field}NotReplicas"]
85
+ available = resource.conditions.Available
86
+ if not available:
87
+ return resource.status.notAvailable
88
+ if not available.status:
89
+ if available.reason:
90
+ return resource.status.notAvailable[available.reason]
91
+ return resource.status.notAvailable
92
+ return resource.observed.metadata.name
74
93
 
75
94
  class HorizontalPodAutoscaler(Check):
76
95
  apiVersion = 'autoscaling/v2'
77
96
  def ready(self, resource):
78
97
  for type in ('FailedGetScale', 'FailedUpdateScale', 'FailedGetResourceMetric', 'InvalidSelector'):
79
98
  if resource.conditions[type].status:
80
- return False
99
+ return resource.status[f"is{type}"]
81
100
  for type in ('ScalingActive', 'ScalingLimited'):
82
101
  if resource.conditions[type].status:
83
- return True
84
- return False
102
+ return resource.observed.metadata.name
103
+ return resource.status.notScalingActiveOrLimiited
85
104
 
86
105
  class Ingress(Check):
87
106
  apiVersion = 'networking.k8s.io/v1'
88
107
  def ready(self, resource):
89
- return len(resource.status.loadBalancer.ingress) > 0
108
+ if not len(resource.status.loadBalancer.ingress):
109
+ return resource.status.noLoadBalanceIngresses
110
+ return resource.observed.metadata.name
90
111
 
91
112
  class Job(Check):
92
113
  apiVersion = 'batch/v1'
93
114
  def ready(self, resource):
94
115
  for type in ('Failed', 'Suspended'):
95
116
  if resource.conditions[type].status:
96
- return False
97
- return bool(resource.conditions.Complete.status)
117
+ return resource.status[f"is{type}"]
118
+ complete = resource.conditions.Complete
119
+ if not complete:
120
+ return resource.status.notComplete
121
+ if not complete.status:
122
+ if complete.reason:
123
+ return resource.status.notComplete[complete.reason]
124
+ return resource.status.notComplete
125
+ return resource.observed.metadata.name
98
126
 
99
127
  class Namespace(AlwaysReady):
100
128
  apiVersion = 'v1'
@@ -102,27 +130,33 @@ class Namespace(AlwaysReady):
102
130
  class PersistentVolumeClaim(Check):
103
131
  apiVersion = 'v1'
104
132
  def ready(self, resource):
105
- return resource.status.phase == 'Bound'
133
+ if resource.status.phase != 'Bound':
134
+ return resource.status.phaseNotBound
135
+ return resource.observed.metadata.name
106
136
 
107
137
  class Pod(Check):
108
138
  apiVersion = 'v1'
109
139
  def ready(self, resource):
110
140
  if resource.status.phase == 'Succeeded':
111
- return True
141
+ return resource.observed.metadata.name
112
142
  if resource.status.phase == 'Running':
113
143
  if resource.observed.spec.restartPolicy == 'Always':
114
144
  if resource.conditions.Ready.status:
115
- return True
116
- return False
145
+ return resource.observed.metadata.name
146
+ return resource.status.notSucceededOrRunning
117
147
 
118
148
  class ReplicaSet(Check):
119
149
  apiVersion = 'v1'
120
150
  def ready(self, resource):
121
151
  if int(resource.status.observedGeneration) < int(resource.observed.metadata.generation):
122
- return False
152
+ return resource.status.priorObservedGeneration
123
153
  if resource.conditions.ReplicaFailure.status:
124
- return False
125
- return int(resource.status.availableReplicas) >= int(resource.observed.spec.replicas or 1)
154
+ if resource.conditions.ReplicaFailure.reason:
155
+ return resource.status.isReplicaFailure[resource.conditions.ReplicaFailure.reason]
156
+ return resource.status.isReplicaFailure
157
+ if int(resource.status.availableReplicas) < int(resource.observed.spec.replicas or 1):
158
+ return resource.status.tooFewavailableReplicas
159
+ return resource.observed.metadata.name
126
160
 
127
161
  class Role(AlwaysReady):
128
162
  apiVersion = 'rbac.authorization.k8s.io/v1'
@@ -137,8 +171,10 @@ class Service(Check):
137
171
  apiVersion = 'v1'
138
172
  def ready(self, resource):
139
173
  if resource.observed.spec.type != 'LoadBalancer':
140
- return True
141
- return len(resource.status.loadBalancer.ingress) > 0
174
+ return resource.observed.metadata.name
175
+ if not len(resource.status.loadBalancer.ingress):
176
+ return resource.status.noLoadBalancerIngresses
177
+ return resource.observed.metadata.name
142
178
 
143
179
  class ServiceAccount(AlwaysReady):
144
180
  apiVersion = 'v1'
@@ -147,7 +183,12 @@ class StatefulSet(Check):
147
183
  apiVersion = 'apps/v1'
148
184
  def ready(self, resource):
149
185
  replicas = resource.observed.spec.replicas or 1
150
- return (resource.status.readyReplicas == replicas and
151
- resource.status.currentReplicas == replicas and
152
- resource.status.currentRevision == resource.status.updateRevision
153
- )
186
+ for field in ('readyReplicas', 'currentReplicas'):
187
+ value = resource.status[field]
188
+ if not value:
189
+ return value
190
+ if replicas != value:
191
+ return resource.status[F"{field}NotReplicas"]
192
+ if resource.status.currentRevision != resource.status.updateRevision:
193
+ return resource.status.currentRevisionNotUpdateReivsion
194
+ return resource.observed.metadata.name
@@ -33,6 +33,13 @@ class Command:
33
33
  metavar='WIDTH',
34
34
  help='Width of the logger name in the log output, default 40.',
35
35
  )
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
+ )
36
43
  parser.add_argument(
37
44
  '--python-path',
38
45
  action='append',
@@ -70,6 +77,11 @@ class Command:
70
77
  logger = logging.getLogger()
71
78
  logger.handlers = [handler]
72
79
  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())
73
85
 
74
86
  for path in reversed(self.args.python_path):
75
87
  sys.path.insert(0, str(pathlib.Path(path).expanduser().resolve()))
@@ -3,6 +3,7 @@ import datetime
3
3
  from google.protobuf.duration_pb2 import Duration
4
4
  from crossplane.function.proto.v1 import run_function_pb2 as fnv1
5
5
 
6
+ from . import auto_ready
6
7
  from . import protobuf
7
8
 
8
9
 
@@ -69,21 +70,22 @@ class TTL:
69
70
 
70
71
  class Ready:
71
72
  def __get__(self, composite, objtype=None):
72
- ready = composite.desired._parent.ready
73
- if ready == fnv1.Ready.READY_TRUE:
73
+ if hasattr(composite, '_ready'):
74
+ return composite._ready
75
+ if composite.desired._parent.ready == fnv1.Ready.READY_TRUE:
74
76
  return True
75
- if ready == fnv1.Ready.READY_FALSE:
77
+ if composite.desired._parent.ready == fnv1.Ready.READY_FALSE:
76
78
  return False
77
79
  return None
78
80
 
79
81
  def __set__(self, composite, ready):
82
+ composite._ready = ready
80
83
  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
84
+ composite.desired._parent.ready = fnv1.Ready.READY_TRUE
85
+ elif ready is None:
86
+ composite.desired._parent.ready = fnv1.Ready.READY_UNSPECIFIED
84
87
  else:
85
- ready = fnv1.Ready.READY_FALSE
86
- composite.desired._parent.ready = ready
88
+ composite.desired._parent.ready = fnv1.Ready.READY_FALSE
87
89
 
88
90
 
89
91
  class BaseComposite:
@@ -111,9 +113,9 @@ class BaseComposite:
111
113
  self.environment = self.context['apiextensions.crossplane.io/environment']
112
114
  self.requireds = Requireds(self)
113
115
  self.resources = Resources(self)
114
- self.unknownsFatal = True
115
116
  self.autoReady = True
116
117
  self.usages = False
118
+ self.unknownsFatal = False
117
119
 
118
120
  observed = self.request.observed.composite
119
121
  desired = self.response.desired.composite
@@ -231,6 +233,7 @@ class Resources:
231
233
 
232
234
  class Resource:
233
235
  def __init__(self, composite, name):
236
+ self._composite = composite
234
237
  self.name = name
235
238
  observed = composite.request.observed.resources[name]
236
239
  desired = composite.response.desired.resources[name]
@@ -238,16 +241,22 @@ class Resource:
238
241
  self.desired = desired.resource
239
242
  self.conditions = Conditions(observed)
240
243
  self.connection = observed.connection_details
241
- self.unknownsFatal = None
242
244
  self.autoReady = None
243
245
  self.usages = None
246
+ self.unknownsFatal = None
244
247
 
245
- def __call__(self, apiVersion=_notset, kind=_notset, namespace=_notset, name=_notset):
248
+ def __call__(self, kind=_notset, apiVersion=_notset, namespace=_notset, name=_notset):
246
249
  self.desired()
250
+ if kind != _notset:
251
+ # Allow for apiVersion in the first arg and kind in the second arg
252
+ if '/' in kind or kind == 'v1':
253
+ if apiVersion != _notset:
254
+ self.kind = apiVersion
255
+ apiVersion = kind
256
+ else:
257
+ self.kind = kind
247
258
  if apiVersion != _notset:
248
259
  self.apiVersion = apiVersion
249
- if kind != _notset:
250
- self.kind = kind
251
260
  if namespace != _notset:
252
261
  self.metadata.namespace = namespace
253
262
  if name != _notset:
@@ -272,9 +281,12 @@ class Resource:
272
281
 
273
282
  @property
274
283
  def externalName(self):
275
- if 'crossplane.io/external-name' in self.metadata.annotations:
276
- return self.metadata.annotations['crossplane.io/external-name']
277
- return self.observed.metadata.annotations['crossplane.io/external-name']
284
+ name = self.metadata.annotations['crossplane.io/external-name']
285
+ if not name:
286
+ name = self.observed.metadata.annotations['crossplane.io/external-name']
287
+ if name:
288
+ self.externalName = name
289
+ return name
278
290
 
279
291
  @externalName.setter
280
292
  def externalName(self, name):
@@ -296,6 +308,7 @@ class Resource:
296
308
  def spec(self, spec):
297
309
  self.desired.spec = spec
298
310
 
311
+ # Used by Secret:v1
299
312
  @property
300
313
  def type(self):
301
314
  return self.desired.type
@@ -318,23 +331,60 @@ class Resource:
318
331
 
319
332
  @property
320
333
  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
334
+ if not hasattr(self, '_ready'):
335
+ if self.desired._parent.ready == fnv1.Ready.READY_TRUE:
336
+ self._ready = True
337
+ elif self.desired._parent.ready == fnv1.Ready.READY_FALSE:
338
+ self._ready = False
339
+ else:
340
+ self._ready = None
341
+ if self.autoReady or (self.autoReady is None and self._composite.autoReady):
342
+ ready = auto_ready.resource_ready(self)
343
+ if ready:
344
+ self._ready = ready
345
+ self.desired._parent.ready = fnv1.Ready.READY_TRUE
346
+ return self._ready
327
347
 
328
348
  @ready.setter
329
349
  def ready(self, ready):
350
+ self._ready = ready
330
351
  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
352
+ self.desired._parent.ready = fnv1.Ready.READY_TRUE
353
+ elif ready is None:
354
+ self.desired._parent.ready = fnv1.Ready.READY_UNSPECIFIED
334
355
  else:
335
- ready = fnv1.Ready.READY_FALSE
336
- self.desired._parent.ready = ready
356
+ self.desired._parent.ready = fnv1.Ready.READY_FALSE
337
357
 
358
+ def setReadyCondition(self, type='Ready'):
359
+ condition = self.conditions[type]
360
+ if condition.status:
361
+ self.ready = self.observed.metadata.name
362
+ else:
363
+ error = f"not{type}Condition"
364
+ if condition.reason:
365
+ self.ready = self.status[error][condition.reason]
366
+ else:
367
+ self.ready = self.status[error]
368
+
369
+ def addDependency(self, resource, field=_notset):
370
+ if field is _notset:
371
+ field = resource.ready
372
+ if field is None:
373
+ field = auto_ready.resource_ready(resource)
374
+ if field is None:
375
+ field = False
376
+ resource.ready = field
377
+ elif field is None:
378
+ field = True
379
+ if not isinstance(field, (protobuf.FieldMessage, protobuf.Value)):
380
+ if field:
381
+ field = resource.observed.metadata.name
382
+ else:
383
+ if not resource.observed.metadata.name:
384
+ field = resource.observed.metadata.name
385
+ else:
386
+ field = resource.status.notReady
387
+ self.metadata.annotations[f"Dependency{resource.name}"] = field
338
388
 
339
389
  class Requireds:
340
390
  def __init__(self, composite):
@@ -408,12 +458,18 @@ class RequiredResources:
408
458
  self._resources = composite.request.required_resources[name]
409
459
  self._cache = {}
410
460
 
411
- def __call__(self, apiVersion=_notset, kind=_notset, namespace=_notset, name=_notset, labels=_notset):
461
+ def __call__(self, kind=_notset, apiVersion=_notset, namespace=_notset, name=_notset, labels=_notset):
412
462
  self._selector()
463
+ if kind != _notset:
464
+ # Allow for apiVersion in the first arg and kind in the second arg
465
+ if '/' in kind or kind == 'v1':
466
+ if apiVersion != _notset:
467
+ self.kind = apiVersion
468
+ apiVersion = kind
469
+ else:
470
+ self.kind = kind
413
471
  if apiVersion != _notset:
414
472
  self.apiVersion = apiVersion
415
- if kind != _notset:
416
- self.kind = kind
417
473
  if namespace != _notset:
418
474
  self.namespace = namespace
419
475
  if name != _notset:
@@ -802,60 +858,36 @@ class _Connection:
802
858
 
803
859
  @property
804
860
  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
861
+ return self._composite.response.observed.composite.connection_details
811
862
 
812
863
  def __getattr__(self, key):
813
864
  return self[key]
814
865
 
815
866
  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
867
+ return self._composite.response.desired.composite.connection_details[key]
822
868
 
823
869
  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)
870
+ return bool(self._composite.response.desired.composite.connection_details)
827
871
 
828
872
  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)
873
+ return len(self._composite.response.desired.composite.connection_details)
832
874
 
833
875
  def __contains__(self, key):
834
- if self._composite.crossplane_v1:
835
- return key in self._composite.response.desired.composite.connection_details
876
+ return key in self._composite.response.desired.composite.connection_details
836
877
 
837
878
  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)
879
+ for key, value in self._composite.response.desired.composite.connection_details:
880
+ yield key, value
844
881
 
845
882
  def __str__(self):
846
883
  return format(self)
847
884
 
848
885
  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)
886
+ return format(self._composite.response.desired.composite.connection_details, spec)
855
887
 
856
888
  def __call__(self, **kwargs):
889
+ self._composite.response.desired.composite.connection_details(**kwargs)
857
890
  if self._composite_v1:
858
- self._composite.response.desired.composite.connection_details(**kwargs)
859
891
  return
860
892
  del self._composite.resources[self._resource_name]
861
893
  for key, value in kwargs:
@@ -872,16 +904,13 @@ class _Connection:
872
904
  if not value:
873
905
  return
874
906
  value = str(value)
875
- if self._composite.crossplane_v1:
876
- self._composite.response.desired.composite.connection_details[key] = value
907
+ self._composite.response.desired.composite.connection_details[key] = value
908
+ if self._composite.crossplane_v1 or not self._composite.connectionSecret.name:
877
909
  return
878
- #if not self._composite.connectionSecret.name:
879
- # return
880
910
  if self._resource_name in self._composite.resources:
881
911
  secret = self._composite.resources[self._resource_name]
882
912
  else:
883
913
  secret = self._composite.resources[self._resource_name]('v1', 'Secret')
884
- print(bool(self._composite.connectionSecret.name), len(self._composite.connectionSecret.name))
885
914
  if self._composite.connectionSecret.name and len(self._composite.connectionSecret.name):
886
915
  secret.metadata.name = self._composite.connectionSecret.name
887
916
  if not self._composite.metadata.namespace:
@@ -896,8 +925,8 @@ class _Connection:
896
925
  del self[key]
897
926
 
898
927
  def __delitem__(self, key):
928
+ del self._composite.response.desired.composite.connection_details[key]
899
929
  if self._composite.crossplane_v1:
900
- del self._composite.response.desired.composite.connection_details[key]
901
930
  return
902
931
  if self._resource_name in self._composite.resources:
903
932
  del self._composite.resources[self._resource_name].data[key]
@@ -9,7 +9,6 @@ import sys
9
9
  import grpc
10
10
  from crossplane.function.proto.v1 import run_function_pb2 as fnv1
11
11
  from crossplane.function.proto.v1 import run_function_pb2_grpc as grpcv1
12
- from . import auto_ready
13
12
  from .. import pythonic
14
13
 
15
14
  logger = logging.getLogger(__name__)
@@ -110,7 +109,13 @@ class FunctionRunner(grpcv1.FunctionRunnerService):
110
109
  iteration = int(step.iteration) + 1
111
110
  step.iteration = iteration
112
111
  composite.context.iteration = iteration
113
- logger.debug(f"Starting compose, {ordinal(len(composite.context._pythonic))} step, {ordinal(iteration)} pass")
112
+ if iteration == 1 and not logger.isEnabledFor(logging.DEBUG):
113
+ if len(composite.context._pythonic) == 1:
114
+ logger.info('Starting compose')
115
+ else:
116
+ logger.info(f"Starting compose, {ordinal(len(composite.context._pythonic))} step")
117
+ else:
118
+ logger.debug(f"Starting compose, {ordinal(len(composite.context._pythonic))} step, {ordinal(iteration)} pass")
114
119
 
115
120
  try:
116
121
  result = composite.compose()
@@ -120,11 +125,13 @@ class FunctionRunner(grpcv1.FunctionRunnerService):
120
125
  return self.fatal(request, logger, 'Compose', e)
121
126
 
122
127
  if requireds := self.get_requireds(step, composite):
123
- logger.info(f"Requireds requested: {','.join(requireds)}")
128
+ logger.debug(f"Requireds requested: {','.join(requireds)}")
124
129
  else:
125
130
  self.process_usages(composite)
126
131
  self.process_unknowns(composite)
127
- auto_ready.process(composite)
132
+ # Perform auto ready on all resources.
133
+ for name, resource in composite.resources:
134
+ resource.ready
128
135
  logger.info('Completed compose')
129
136
 
130
137
  return composite.response._message
@@ -322,9 +329,11 @@ class FunctionRunner(grpcv1.FunctionRunnerService):
322
329
  name = name.split('.')
323
330
  for values in (
324
331
  ('request', 'observed', 'composite', 'resource'),
332
+ ('response', 'desired', 'composite', 'resource'),
325
333
  ('request', 'observed', 'resources', None, 'resource'),
326
- ('request', 'extra_resources', None, 'items', None, 'resource'),
327
334
  ('response', 'desired', 'resources', None, 'resource'),
335
+ ('request', 'required_resources', None, 'items', None, 'resource'),
336
+ ('request', 'extra_resources', None, 'items', None, 'resource'),
328
337
  ):
329
338
  if len(values) < len(name):
330
339
  ix = 0