Skip to content
This repository has been archived by the owner on Jul 7, 2024. It is now read-only.

Commit

Permalink
Merge pull request #9 from salemove/rm-yaml
Browse files Browse the repository at this point in the history
  • Loading branch information
take-five authored Jun 24, 2024
2 parents 9576b0e + 1bc9666 commit 7ebe640
Show file tree
Hide file tree
Showing 22 changed files with 28,262 additions and 158 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ on:
version:
description: Package version (e.g. v0.1.0)
required: false
prerelease:
description: 'Publish as a prerelease'
required: false
default: false
type: boolean

env:
# Common versions
Expand Down Expand Up @@ -161,3 +166,19 @@ jobs:
- name: Push Multi-Platform Package to Docker Hub
if: env.XPKG_ACCESS_ID != ''
run: "./crossplane --verbose xpkg push --package-files $(echo *.xpkg|tr ' ' ,) ${{ env.XPKG }}:${{ env.XPKG_VERSION }}"

- name: Create Tag
if: inputs.version != ''
uses: negz/create-tag@39bae1e0932567a58c20dea5a1a0d18358503320 # v1
with:
version: ${{ inputs.version }}
message: 'Release ${{ inputs.version }}'
token: ${{ secrets.GITHUB_TOKEN }}

- name: Create Release
if: inputs.version != ''
uses: softprops/action-gh-release@v2
with:
prerelease: ${{ inputs.prerelease }}
name: ${{ inputs.version }}
tag_name: ${{ inputs.version }}
47 changes: 38 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ kind: Function
metadata:
name: function-javascript
spec:
package: docker.io/salemove/crossplane-function-javascript:v0.2.0
package: docker.io/salemove/crossplane-function-javascript:v0.3.0
EOF
```

Expand Down Expand Up @@ -111,8 +111,6 @@ a default function. The exported function is called with 2 arguments:
Connection details from other observed resources are already Base64-encoded, so
you can pass their values to `setConnectionDetails` function as is:
```javascript
import * as Base64 from 'base64';

export default function (req, rsp) {
// ...skip for brevity
const username = req.observed.resources.user.connectionDetails.username;
Expand Down Expand Up @@ -140,6 +138,8 @@ doesn't support external dependencies or Node.js modules. However, users can use
or [Webpack][webpack], or any other similar tool to bundle external dependencies into a single JavaScript
file, and inject it into the composition pipeline as a single blob.

See [`external-dependencies`](examples/external-dependencies) example in the [`examples/`](./examples) folder.

For convenience, the runtime includes some "faux" external packages:

* `console` - implements some of the JavaScript's Console API static methods. The output is logged in the
Expand Down Expand Up @@ -167,12 +167,40 @@ For convenience, the runtime includes some "faux" external packages:
// this will work in your composition function, but won't work in browsers
btoa("a Ā 𐀀 文 🦄")
```
* `yaml` - includes functions for encoding and decoding objects into YAML format:
```javascript
import * as YAML from 'yaml';
const enc = YAML.stringify(someObject);
const dec = YAML.parse(enc);
```

## Code transpilation

[Goja][goja] natively only supports ECMAScript 5.1 syntax, so in order to use modern syntax features,
the source code must be _transpiled_ into a ES 5.1 syntax. For convenience, transpilation is built-in
into the function server and is enabled by default.

For large functions, however, this additional pre-processing can impact performance, so if the function
is already written in ES 5.1 compatible syntax (or pre-processed before injecting the source into a Composition),
you can disable server-side transpilation:

```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: function-javascript
spec:
compositeTypeRef:
apiVersion: example.crossplane.io/v1
kind: XR
mode: Pipeline
pipeline:
- step: run-the-template
functionRef:
name: function-javascript
input:
apiVersion: javascript.fn.crossplane.io/v1beta1
kind: Input
spec:
source:
transpile: false # <-- disable transpilation
inline: |
// source code
```

## Developing this function

Expand Down Expand Up @@ -205,3 +233,4 @@ $ make xpkg.build
[esbuild]: https://esbuild.github.io/
[webpack]: https://webpack.js.org/
[base64]: https://developer.mozilla.org/en-US/docs/Glossary/Base64
[Babel]: https://babeljs.io/
2 changes: 1 addition & 1 deletion example/Makefile → examples/basic/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ render:
@crossplane beta render -r xr.yaml composition.yaml functions.yaml

run:
$(MAKE) -C .. run
$(MAKE) -C ../.. run
8 changes: 2 additions & 6 deletions example/README.md → examples/basic/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Example manifests
# JavaScript Function Example

You can run your function locally and test it using `crossplane beta render`
with these example manifests.
Expand All @@ -17,11 +17,7 @@ kind: XR
metadata:
name: example-xr
---
apiVersion: render.crossplane.io/v1beta1
kind: Result
message: I was run with input "Hello world"!
severity: SEVERITY_NORMAL
step: run-the-template
# ... results
```

Stop the function running in background:
Expand Down
4 changes: 1 addition & 3 deletions example/composition.yaml → examples/basic/composition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ spec:
input-val-2: "Hello"
spec:
source:
transpile: true
inline: |
import * as YAML from 'yaml';
export default (req, rsp) => {
console.log("request", JSON.stringify(req, null, 2));
Expand All @@ -44,7 +43,6 @@ spec:
name: `test-${region}`,
region: region,
compositeRegion: req.observed.composite.resource.spec.region,
yamlTest: YAML.stringify({ foo: "bar", bax: [12, 23] }),
b64test: btoa('abcdefgh')
}
}
Expand Down
2 changes: 1 addition & 1 deletion example/functions.yaml → examples/basic/functions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ metadata:
render.crossplane.io/runtime: Development
spec:
# This is ignored when using the Development runtime.
package: docker.io/salemove/crossplane-function-javascript:v0.2.0
package: docker.io/salemove/crossplane-function-javascript:v0.3.0
File renamed without changes.
1 change: 1 addition & 0 deletions examples/external-dependencies/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
15 changes: 15 additions & 0 deletions examples/external-dependencies/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.PHONY: render run build

render: build
@crossplane beta render -r xr.yaml composition.yaml functions.yaml

run:
$(MAKE) -C ../.. run

build: composition.yaml node_modules

composition.yaml: build.mjs src/index.js package.json package-lock.json
@npm run build

node_modules:
@npm i
51 changes: 51 additions & 0 deletions examples/external-dependencies/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Building a function with external dependencies

This example demonstrates how to package external dependencies into a
single text file and package it into a Crossplane Composition resource.

The function source code is located in [`src/index.js`](./src/index.js) file,
and it uses NPM package [YAML](https://www.npmjs.com/package/yaml) as an external
dependency.

Eternal dependencies are bundled into a single file by [esbuild] and then transpiled
with [Babel] to ES5 syntax supported by [Goja]. The resulting source code is used to
build the [`composition.yaml`](./composition.yaml) file.

By default, the function server also _transpiles_ the input code into ES 5.1 syntax using
[Babel], but since the input code is already ES 5.1, `.spec.source.transpile` is set to `false`.
Setting this flag for large bundles can significantly improve performance.

[esbuild]: https://esbuild.github.io/
[Goja]: https://github.com/dop251/goja
[Babel]: https://babeljs.io/

## Running this example

Make sure you have Node.js installed.

You can run your function locally and test it using `crossplane beta render`
with these example manifests.

Run the function locally in the background:
```shell
$ make run &
```

Then call it with example manifests:
```shell
$ make render
---
apiVersion: example.crossplane.io/v1
kind: XR
metadata:
name: example-xr
---
# ...function results
```

Stop the function running in background:
```shell
$ fg
# Press Ctrl-C
^C
```
67 changes: 67 additions & 0 deletions examples/external-dependencies/build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import process from 'node:process';
import fs from 'node:fs/promises';
import * as esbuild from 'esbuild';
import babel from '@babel/core';
import YAML from 'yaml';

const buildResult = await esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
write: false,
platform: "neutral",
sourcemap: "inline",
sourceRoot: "examples/dependencies",
target: "es6"
});

if (buildResult.errors.length > 0) {
console.log(buildResult.errors);
process.exit(1);
}

const transpiled = await babel.transformAsync(buildResult.outputFiles[0].text, {
plugins: [
["@babel/plugin-transform-modules-commonjs", { loose: true }],
],
ast: false,
babelrc: false,
sourceMaps: 'inline',
inputSourceMap: true,
compact: false,
retainLines: true,
highlightCode: false
});

const composition = {
apiVersion: 'apiextensions.crossplane.io/v1',
kind: 'Composition',
metadata: { name: 'function-javascript' },
spec: {
compositeTypeRef: {
apiVersion: 'example.crossplane.io/v1',
kind: 'XR'
},
mode: 'Pipeline',
pipeline: [{
step: 'run-the-template',
functionRef: {
name: 'function-javascript',
},
input: {
apiVersion: 'javascript.fn.crossplane.io/v1beta1',
kind: 'Input',
metadata: {
annotations: { key: 'value' },
},
spec: {
source: {
transpile: false,
inline: transpiled.code
}
}
}
}]
}
};

await fs.writeFile('./composition.yaml', YAML.stringify(composition));
Loading

0 comments on commit 7ebe640

Please sign in to comment.