Skip to content

Commit ef5b3a1

Browse files
committed
Remove single use XRD and Composition, Crossplane does not like them in function packages
Signed-off-by: Patrick J. McNerthney <pat@mcnerthney.com>
1 parent 3b0079a commit ef5b3a1

19 files changed

Lines changed: 205 additions & 279 deletions

README.md

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -385,25 +385,78 @@ optionally to the Claim.
385385
| Result.message | String | Human-readable details about the result |
386386
| Result.claim | Boolean | Also apply the result to the claim |
387387

388-
## Single use Composites
388+
## Inlined Composites
389389

390390
Tired of creating a CompositeResourceDefinition, a Composition, and a Composite
391-
just to run that Composition once in a single use or initialize task?
391+
just to run that Composition once in a setup or initialize task?
392392

393-
function-pythonic installs a `Composite` CompositeResourceDefinition that enables
394-
creating such tasks using a single Composite resource:
393+
function-pythonic supports "inlined" Compositions, where the python module
394+
from a field in the Composite's spec.
395395
```yaml
396-
apiVersion: pythonic.fn.crossplane.io/v1alpha1
397-
kind: Composite
396+
apiVersion: inlined.example.org/v1alpha1
397+
kind: Step
398398
metadata:
399-
name: composite-example
399+
name: inlined-example
400400
spec:
401401
composite: |
402402
class HelloComposite(BaseComposite):
403403
def compose(self):
404-
self.status.composite = 'Hello, World!'
404+
self.status.step = 'Hello, World!'
405+
```
406+
The CompositeResourceDefinition and Composition to support the above example:
407+
```yaml
408+
apiVersion: apiextensions.crossplane.io/v1
409+
kind: CompositeResourceDefinition
410+
metadata:
411+
name: inlined.example.org/v1alpha1
412+
spec:
413+
group: inlined.example.org
414+
names:
415+
kind: Step
416+
plural: steps
417+
defaultCompositionRef:
418+
name: steps.inlined.example.org
419+
versions:
420+
- name: v1alpha1
421+
served: true
422+
referenceable: true
423+
schema:
424+
openAPIV3Schema:
425+
type: object
426+
properties:
427+
spec:
428+
type: object
429+
properties:
430+
composite:
431+
type: string
432+
description: 'A Python module that defines a class with the signature: class Composite(BaseComposite)'
433+
required:
434+
- composite
435+
status:
436+
type: object
437+
properties:
438+
composite:
439+
x-kubernetes-preserve-unknown-fields: true
440+
```
441+
```yaml
442+
apiVersion: apiextensions.crossplane.io/v1
443+
kind: Composition
444+
metadata:
445+
name: steps.inlined.example.org
446+
spec:
447+
compositeTypeRef:
448+
apiVersion: inlined.example.org/v1alpha1
449+
kind: Step
450+
mode: Pipeline
451+
pipeline:
452+
- step: inlined
453+
functionRef:
454+
name: function-pythonic
455+
input:
456+
apiVersion: pythonic.fn.crossplane.io/v1alpha1
457+
kind: Composite
458+
inlined: composite
405459
```
406-
407460
## Quick Start Development
408461

409462
function-pythonic includes a pure python implementation of the `crossplane render ...`

crossplane/pythonic/composite.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def __set__(self, composite, ready):
8989

9090

9191
class BaseComposite:
92-
def __init__(self, crossplane_v1, request, single_use, logger):
92+
def __init__(self, crossplane_v1, request, logger):
9393
self.crossplane_v1 = crossplane_v1
9494
self.request = protobuf.Message(None, 'request', request.DESCRIPTOR, request, 'Function Request')
9595
response = fnv1.RunFunctionResponse(
@@ -104,10 +104,7 @@ def __init__(self, crossplane_v1, request, single_use, logger):
104104
)
105105
self.response = protobuf.Message(None, 'response', response.DESCRIPTOR, response)
106106
self.logger = logger
107-
if single_use:
108-
self.parameters = self.request.observed.composite.resource.spec.parameters
109-
else:
110-
self.parameters = self.request.input.parameters
107+
self.parameters = self.request.input.parameters
111108
self.credentials = Credentials(self.request)
112109
self.context = self.response.context
113110
self.environment = self.context['apiextensions.crossplane.io/environment']

crossplane/pythonic/function.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,13 @@ async def run_function(self, request):
4848
name.append(composite['metadata']['name'])
4949
logger = logging.getLogger('.'.join(name))
5050

51-
if composite['apiVersion'] in ('pythonic.crossplane.io/v1alpha1', 'pythonic.fortra.com/v1alpha1') and composite['kind'] == 'Composite':
52-
if 'spec' not in composite or 'composite' not in composite['spec']:
53-
return self.fatal(request, logger, 'Missing spec "composite"')
54-
single_use = True
55-
composite = composite['spec']['composite']
51+
if 'inlined' in request.input and request.input['inlined']:
52+
if 'spec' not in composite or request.input['inlined'] not in composite['spec']:
53+
return self.fatal(request, logger, f"Missing inlined spec.{request.input['inlined']}")
54+
composite = composite['spec'][request.input['inlined']]
5655
else:
5756
if 'composite' not in request.input:
5857
return self.fatal(request, logger, 'Missing input "composite"')
59-
single_use = False
6058
composite = request.input['composite']
6159

6260
# Ideally this is something the Function API provides
@@ -100,7 +98,7 @@ async def run_function(self, request):
10098
self.clazzes[composite] = clazz
10199

102100
try:
103-
composite = clazz(self.crossplane_v1, request, single_use, logger)
101+
composite = clazz(self.crossplane_v1, request, logger)
104102
except Exception as e:
105103
return self.fatal(request, logger, 'Instantiate', e)
106104

crossplane/pythonic/protobuf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,8 +796,10 @@ def __len__(self):
796796
def __contains__(self, item):
797797
match self._kind:
798798
case 'struct_value':
799+
item = self._validate_key(item)
799800
return item in self._value.struct_value.fields or item in self._unknowns
800801
case 'Struct':
802+
item = self._validate_key(item)
801803
return item in self._value.fields or item in self._unknowns
802804
case 'list_value' | 'ListValue':
803805
for value in self:

0 commit comments

Comments
 (0)