diff --git a/config/buildless-serverless/templates/busola-serverless-extension.yaml b/config/buildless-serverless/templates/busola-serverless-extension.yaml new file mode 100644 index 000000000..4c042a49e --- /dev/null +++ b/config/buildless-serverless/templates/busola-serverless-extension.yaml @@ -0,0 +1,598 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: functions + namespace: kube-public + labels: + busola.io/extension: resource + busola.io/extension-version: '0.5' + app.kubernetes.io/instance: buildless-serverless-busola-functions + app.kubernetes.io/component: busola +data: + details: |- + header: + - name: Replicas + widget: Badge + source: "$string($count($filter($replicas().items, function($r){ + $r.status.phase = 'Running'}))) & '/' & $string($count($replicas().items))" + highlights: + critical: "$count($replicas().items) != $count($filter($replicas().items, function($r){ + $r.status.phase = 'Running'}))" + warning: "$count($replicas().items) = 0 and $count($filter($replicas().items, function($r){ + $r.status.phase = 'Running'}) = 0)" # this condition needs to be above 'positive' + positive: "$count($replicas().items) = $count($filter($replicas().items, function($r){ + $r.status.phase = 'Running'}))" + - name: header.status + widget: Badge + highlights: + positive: + - RUNNING + informative: + - INITIALIZING + - DEPLOYING + warning: + - PENDING + - WARNING + critical: + - FAILED + - ERROR + source: >- + ($.status = undefined or $.status.conditions = undefined or + $count($.status.conditions) = 0) ? 'INITIALIZING' : + $count($filter($.status.conditions, function($v) { $v.status = 'False' })) + != 0 ? $count($filter($.status.conditions, function($v) { $v.type = + 'Running' and $v.status = 'True' })) != 0 ? 'WARNING' : 'FAILED' : + $count($filter($.status.conditions, function($v) { $v.type = + 'ConfigurationReady' and $v.status = 'True' })) != 0 ? + $count($filter($.status.conditions, + function($v) { $v.type = 'Running' and $v.status = 'True' })) != 0 ? + 'RUNNING' : $count($filter($.status.conditions, function($v) { $v.type = + 'Running' and $v.status = 'Unknown' and $v.reason = + 'MinReplicasNotAvailable' })) != 0 ? 'PENDING' : 'DEPLOYING' : 'INITIALIZING' + description: >- + ($.status = undefined or $.status.conditions = undefined or + $count($.status.conditions) = 0) ? null : + $count($filter($.status.conditions, function($v) { $v.status = 'False' })) + != 0 ? $count($filter($.status.conditions, function($v) { $v.type = + 'Running' and $v.status = 'True' })) != 0 ? 'New revision error: ' & + $filter($.status.conditions, function($v) { $v.status = 'False' + })[0].message : 'Error: ' & $filter($.status.conditions, function($v) { + $v.status = 'False' })[0].message : null + - name: header.sourceType + source: 'spec.source.gitRepository ? "Git Repository" : "Inline Editor"' + - name: header.runtime + source: >- + spec.runtime = 'python312' ? 'Python 3.12' : (spec.runtime = 'nodejs22' ? 'Node.js 22' : (spec.runtime = 'nodejs20' ? 'Node.js 20' : spec.runtime)) + body: + - widget: Tabs + children: + - name: tabs.code + children: + - source: spec.source.inline.source + widget: CodeViewer + name: code.source + language: '$contains($root.spec.runtime, "python") ? "python": "javascript"' + visibility: $exists($value) + - source: spec.source.inline.dependencies + widget: CodeViewer + name: code.dependencies + language: '"json"' + visibility: $exists($value) + - source: spec.source.gitRepository + widget: Panel + name: code.gitRepositoryConfig + visibility: $exists($value) + children: + - name: code.gitRepository.url + source: url + - name: code.gitRepository.reference + source: reference + - name: code.gitRepository.baseDir + source: baseDir + - name: code.gitRepository.auth + visibility: $exists($value) + widget: Panel + source: auth + children: + - name: code.gitRepository.auth.secretName + widget: ResourceLink + source: secretName + resource: + kind: "'Secret'" + name: secretName + namespace: $root.metadata.namespace + - name: code.gitRepository.auth.type + source: type + - source: spec.env + widget: Table + name: code.env + children: + - source: $item.name + name: code.env.name + - source: $item.value + name: code.env.value + - name: code.env.valueFrom + widget: ResourceLink + source: >- + $exists($item.valueFrom.configMapKeyRef)? + $item.valueFrom.configMapKeyRef.name : + $item.valueFrom.secretKeyRef.name + resource: + name: >- + $exists($item.valueFrom.configMapKeyRef) ? + $item.valueFrom.configMapKeyRef.name : + $item.valueFrom.secretKeyRef.name + namespace: $root.metadata.namespace + kind: >- + $exists($item.valueFrom.configMapKeyRef) ? 'ConfigMap' : + 'Secret' + - name: code.env.source + widget: Badge + source: >- + $exists($item.value) ? 'CUSTOM' : + $exists($item.valueFrom.configMapKeyRef) ? 'CONFIG MAP' : 'SECRET' + - name: code.env.key + source: >- + $exists($item.valueFrom.configMapKeyRef) ? + $item.valueFrom.configMapKeyRef.key : + $exists($item.valueFrom.secretKeyRef) ? + $item.valueFrom.secretKeyRef.key : 'N/A' + - widget: ResourceList + source: $replicas() + name: code.replicas + disableCreate: true + - widget: EventList + filter: $matchEvents($item, $root.kind, $root.metadata.name) + name: events + defaultType: information + hideInvolvedObjects: true + - name: tabs.configuration + children: + - widget: ResourceList + source: $apiRules() + name: configuration.apiRules + disableCreate: true + - widget: ResourceList + source: $subscriptions() + name: configuration.subscriptions + disableCreate: true + - name: tabs.resources + children: + - widget: Columns + inline: false + children: + - name: resources.runtimeProfile + widget: Panel + children: + - name: resources.requests.memory + source: >- + spec.resourceConfiguration.function.resources.requests.memory + - name: resources.requests.cpu + source: spec.resourceConfiguration.function.resources.requests.cpu + - name: resources.limits.memory + source: >- + spec.resourceConfiguration.function.resources.limits.memory + - name: resources.limits.cpu + source: spec.resourceConfiguration.function.resources.limits.cpu + form: |- + - var: sourceType + widget: Text + enum: + - Inline + - Git Repository + dynamicValue: '$exists(spec.source.gitRepository) ? "Git Repository" : "Inline"' + name: header.sourceType + trigger: [sourceType] + - simple: true + type: string + name: Language + var: language + required: true + enum: [JavaScript, Python] + trigger: [language] + dynamicValue: | + spec.runtime in ['nodejs20', 'nodejs22'] ? 'JavaScript' : + spec.runtime in ['python312'] ? 'Python' : + '' + - simple: true + path: spec.runtime + placeholder: placeholders.spec.runtime + enum: | + $language = 'JavaScript' ? ['nodejs20', 'nodejs22'] : + $language = 'Python' ? ['python312'] : + [] + subscribe: + language: | + $language = 'JavaScript' ? ($exists($root.spec.runtime) and $root.spec.runtime != 'python312') ? $root.spec.runtime : 'nodejs20' : + $language = 'Python' ? 'python312' : + '' + - path: spec.resourceConfiguration.function.profile + simple: true + enum: ['XS', 'S', 'M', 'L', 'XL'] + - path: spec.source.inline + visibility: $sourceType = 'Inline' + simple: true + children: + - path: source + widget: CodeEditor + simple: true + language: '$contains($root.spec.runtime, "node") ? "javascript" : "python"' + defaultExpanded: true + subscribe: + sourceType: |- + $sourceType = 'Inline' ? $language = 'JavaScript' ? $exists($root.metadata.creationTimestamp) ? $root.spec.source.inline.source : "/* + If you prefer mjs import/export syntax over cjs you need to specify + 'type': 'module' + in the Function dependencies (package.json) and along with that change the import/export syntax to: + import foo from 'foo' + export function main(event, context) { + //your logic using foo library + return + } + */ + + module.exports = { + main: async function (event, context) { + var queryParams = event['extensions']['request']['query']; + //read query param, for example `?greeting=Hi` + var greetingMsg = queryParams['greeting']; + if(!greetingMsg) { + greetingMsg = 'Hello world'; + } + const message = greetingMsg + + ` from the Kyma Function ${context['function-name']}` + + ` running on ${context.runtime}!`; + console.log(message); + return message; + } + }" : + $language = 'Python' ? $exists($root.metadata.creationTimestamp) ? $root.spec.source.inline.source : "def main(event, context): + request = event['extensions']['request'] + greetingMsg = request.query.get('greeting') + if not greetingMsg: + greetingMsg = 'Hello world' + message = greetingMsg + ' from the Kyma Function '+context['function-name']+' running on '+context['runtime']+ '!'; + print(message) + return message" : + '' : '' + language: |- + $language = 'JavaScript' ? $exists($root.metadata.creationTimestamp) ? $root.spec.source.inline.source : "/* + If you prefer mjs import/export syntax over cjs you need to specify + 'type': 'module' + in the Function dependencies (package.json) and along with that change the import/export syntax to: + import foo from 'foo' + export function main(event, context) { + //your logic using foo library + return + } + */ + + module.exports = { + main: async function (event, context) { + var queryParams = event['extensions']['request']['query']; + + //read query param, for example `?greeting=Hi` + var greetingMsg = queryParams['greeting']; + if(!greetingMsg) { + greetingMsg = 'Hello world'; + } + const message = greetingMsg + + ` from the Kyma Function ${context['function-name']}` + + ` running on ${context.runtime}!`; + console.log(message); + return message; + } + }" : + $language = 'Python' ? $exists($root.metadata.creationTimestamp) ? $root.spec.source.inline.source : "def main(event, context): + request = event['extensions']['request'] + greetingMsg = request.query.get('greeting') + if not greetingMsg: + greetingMsg = 'Hello world' + message = greetingMsg + ' from the Kyma Function '+context['function-name']+' running on '+context['runtime']+ '!'; + print(message) + return message" : + '' + - path: dependencies + widget: CodeEditor + formatAsString: true + language: '$contains($root.spec.runtime, "node") ? "json" : "plaintext"' + - path: spec.source.gitRepository + widget: FormGroup + visibility: $sourceType = 'Git Repository' + defaultExpanded: true + children: + - path: url + - path: baseDir + required: true + - path: reference + required: true + - var: useAuthorization + type: boolean + name: code.gitRepository.auth + dynamicValue: $exists($.spec.source.gitRepository.auth) + - widget: FormGroup + path: auth + visibility: $useAuthorization + children: + - path: secretName + widget: Resource + overwrite: false + visibility: $canI('v1', 'Secret') + resource: + kind: Secret + version: v1 + scope: namespace + - simple: true + var: separator + value: "" + - path: secretName + widget: Text + overwrite: false + visibility: $not($canI('v1', 'Secret')) + - path: type + - path: spec.resourceConfiguration.function + widget: FormGroup + children: + - path: resources.limits + widget: KeyValuePair + - visibility: $boolean($root.spec.resourceConfiguration.function.profile) + severity: warning + alert: "'alert.resources.limits'" + widget: Alert + - path: resources.requests + widget: KeyValuePair + - visibility: $boolean($root.spec.resourceConfiguration.function.profile) + severity: warning + alert: "'alert.resources.requests'" + widget: Alert + - path: spec.env + widget: GenericList + children: + - path: '[]' + children: + - var: envType + widget: Text + name: spec.env.source + enum: + - Custom + - From Config Map + - From Secret + dynamicValue: >- + $exists($item.valueFrom.secretKeyRef) ? 'From Secret' : + ($exists($item.valueFrom.configMapKeyRef) ? 'From Config Map' : + 'Custom') + - path: name + - path: value + visibility: $envType = 'Custom' + - path: valueFrom.secretKeyRef.name + widget: Resource + resource: + kind: Secret + version: v1 + scope: namespace + provideVar: secret + overwrite: false + visibility: $canI('v1', 'Secret') and $envType = 'From Secret' + - simple: true + var: separator + value: "" + - path: valueFrom.secretKeyRef.name + widget: Text + overwrite: false + visibility: $not($canI('v1', 'Secret')) and $envType = 'From Secret' + - path: valueFrom.secretKeyRef.key + widget: Text + enum: $keys($secret.data) + visibility: $envType = 'From Secret' + - path: valueFrom.configMapKeyRef.name + widget: Resource + resource: + kind: ConfigMap + version: v1 + scope: namespace + provideVar: configMap + overwrite: false + visibility: $canI('v1', 'ConfgMap') and $envType = 'From Config Map' + - simple: true + var: separator + value: "" + - path: valueFrom.configMapKeyRef.name + widget: Text + overwrite: false + visibility: $not($canI('v1', 'ConfgMap')) and $envType = 'From Config Map' + - path: valueFrom.configMapKeyRef.key + widget: Text + enum: $keys($configMap.data) + visibility: $envType = 'From Config Map' + - path: spec + widget: FormGroup + children: + - path: labels + widget: KeyValuePair + defaultExpanded: false + - path: annotations + widget: KeyValuePair + defaultExpanded: false + general: |- + resource: + kind: Function + group: serverless.kyma-project.io + version: v1alpha2 + name: Functions + category: Workloads + urlPath: functions + scope: namespace + description: >- + {{"{{[Function](https://kyma-project.io/docs/kyma/latest/05-technical-reference/00-custom-resources/svls-01-function/#documentation-content/)}}"}} + is a simple code snippet that you can run without provisioning or managing + servers. + list: |- + - name: header.runtime + source: >- + spec.runtime = 'python312' ? 'Python 3.12' : (spec.runtime = 'nodejs22' ? 'Node.js 22' :(spec.runtime = 'nodejs20' ? 'Node.js 20' : spec.runtime)) + - name: header.sourceType + source: 'spec.source.gitRepository ? "Git Repository" : "Inline Editor"' + - name: header.status + widget: Badge + highlights: + positive: + - RUNNING + informative: + - INITIALIZING + - DEPLOYING + warning: + - PENDING + - WARNING + critical: + - FAILED + - ERROR + source: >- + ($.status = undefined or $.status.conditions = undefined or + $count($.status.conditions) = 0) ? 'INITIALIZING' : + $count($filter($.status.conditions, function($v) { $v.status = 'False' })) + != 0 ? $count($filter($.status.conditions, function($v) { $v.type = + 'Running' and $v.status = 'True' })) != 0 ? 'WARNING' : 'FAILED' : + $count($filter($.status.conditions, function($v) { $v.type = + 'ConfigurationReady' and $v.status = 'True' })) != 0 ? + $count($filter($.status.conditions, + function($v) { $v.type = 'Running' and $v.status = 'True' })) != 0 ? + 'RUNNING' : $count($filter($.status.conditions, function($v) { $v.type = + 'Running' and $v.status = 'Unknown' and $v.reason = + 'MinReplicasNotAvailable' })) != 0 ? 'PENDING' : 'DEPLOYING' : + 'INITIALIZING' + description: >- + ($.status = undefined or $.status.conditions = undefined or + $count($.status.conditions) = 0) ? null : + $count($filter($.status.conditions, function($v) { $v.status = 'False' })) + != 0 ? $count($filter($.status.conditions, function($v) { $v.type = + 'Running' and $v.status = 'True' })) != 0 ? 'New revision error: ' & + $filter($.status.conditions, function($v) { $v.status = 'False' + })[0].message : 'Error: ' & $filter($.status.conditions, function($v) { + $v.status = 'False' })[0].message : null + dataSources: |- + replicas: + resource: + kind: Pod + version: v1 + filter: >- + ($item.metadata.labels.'serverless.kyma-project.io/function-name' = + $root.metadata.name) and + ($item.metadata.labels.'serverless.kyma-project.io/resource' = 'deployment') + apiRules: + resource: + kind: APIRule + version: v1beta1 + group: gateway.kyma-project.io + filter: $contains($item.spec.service.name, $root.metadata.name) + subscriptions: + resource: + kind: Subscription + version: v1alpha2 + group: eventing.kyma-project.io + filter: $contains($item.spec.sink, $root.metadata.name) + translations: | + en: + tabs.code: Code + tabs.configuration: Configuration + tabs.resources: Resources + code.gitRepositoryConfig: Repository Configuration + code.replicas: Replicas of the Function + code.source: Source + code.dependencies: Dependencies + code.gitRepository.url: URL + code.gitRepository.reference: Reference + code.gitRepository.baseDir: Base Directory + code.gitRepository.auth: Auth + code.gitRepository.auth.secretName: Secret name + code.gitRepository.auth.type: Type + code.env: Environment Variables + code.env.name: Name + code.env.value: Value + code.env.valueFrom: Value From + code.env.source: Source + code.env.key: Key + events: Events + configuration.apiRules: API Rules + configuration.subscriptions: Subscriptions + header.runtime: Runtime + header.status: Status + header.sourceType: Source Type + resources.scalingOptions: Scaling Options + resources.minReplicas: Minimum Replicas + resources.maxReplicas: Maximum Replicas + resources.description: Minimum and maximum number of running Replicas. + resources.runtimeProfile: Runtime Profile + resources.requests.memory: Memory Requests + resources.requests.cpu: CPU Requests + resources.limits.memory: Memory Limits + resources.limits.cpu: CPU Limits + spec.source.inline.dependencies: Dependencies + spec.source.inline.source: Source + spec.env: Environment Variables + Requests: Requests + Limits: Limits + spec.runtime: Runtime + Status: Status + Runtime: Runtime + 'Source Type': Source Type + spec.runtime.nodejs20: Node.js 20 + spec.runtime.nodejs22: Node.js 22 + spec.runtime.python312: Python 3.12 + spec.resourceConfiguration.function: Function + spec.resourceConfiguration.function.profile: Function profile + placeholders.spec.runtime: Choose Function runtime + spec.env.name: Variable Name + spec.env.source: Source + envType: Variable Type + 'Node.js Function': Node.js Function + 'Python Function': Python Function + alert.resources.requests: If you want to provide your own requests configuration, leave the Function profile field empty. + alert.resources.limits: If you want to provide your own limits configuration, leave the Function profile field empty. + spec.labels: Runtime Labels + spec.annotations: Runtime Annotations + presets: |- + - name: Default + default: true + value: + spec: + resourceConfiguration: + function: + profile: XS + - name: Node.js Function + value: + spec: + runtime: nodejs20 + source: + inline: + source: |- + /* + If you prefer mjs import/export syntax over cjs you need to specify + 'type': 'module' + in the Function dependencies (package.json) and along with that change the import/export syntax to: + import foo from 'foo' + export function main(event, context) { + //your logic using foo library + return + } + */ + + module.exports = { + main: async function (event, context) { + const message = `Hello World` + + ` from the Kyma Function ${context["function-name"]}` + + ` running on ${context.runtime}!`; + console.log(message); + return message; + } + } + - name: Python Function + value: + spec: + runtime: python312 + source: + inline: + source: |- + def main(event, context): + message = "Hello World from the Kyma Function "+context['function-name']+" running on "+context['runtime']+ "!"; + print(message) + return message