Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,35 @@
# swhub-custom-app-samples
# Software Hub Custom Apps Samples

IBM Software Hub offered custom application capablity in 5.3, the purpose of the git repo is to host the sample applications for end user to download and try out.

The repo contains collection of custom sample apps that can be deployed into dataplane/phsical location, each folder contains one sample app and README instructions for deployment

### Pre-requisites to deploy sample applications

Custom Apps is built on top of remote dataplanes feature. refer [this doc](https://www.ibm.com/docs/en/software-hub/5.2.x?topic=installing-setting-up-remote-physical-location) to understand concept of remote dataplane and physical locations

`default dataplane` is a dataplane that resides locally on a regular software hub cluster, that are designated for deploying custom apps. for setting up default dataplane, the following component are required:

- Software Hub Scheduling Service
refer [this doc](https://www.ibm.com/docs/en/software-hub/5.2.x?topic=cluster-installing-shared-components) for how to install scheduling service as cluster component
- Software Hub 5.3 premium cartrige and cpd-cli olm-utils premium image

To enable default dataplane using cpd-cli:

1. load olm-utils premium image: `export OLM_UTILS_IMAGE=icr.io/cpopen/cpd/olm-utils-v4:5.3.0-<premium image tag>`
2. Run `cpd-cli manage login-to-ocp -u kubeadmin -p <password> --server=<ocp_url>`
3. Run `cpd-cli manage enable-premuim-features --license_acceptance=true --features=enable_rdp --operator_ns=<project name> --instance_ns=<project name> --scheduler_ns=<project>`
4. Create two namespaces mgmt and workload(wl).
5. Run `cpd-cli manage enable-default-dataplane --instance_ns=zen --management_ns=mgmt --workload_ns=wl` this command will create a default physical location - `default-pl` and a default dataplane - `default-dp`.

overview of custom applocations included in this example, for demostating application types supported
|Name|Application Type|Folder||
|:---|:---|:---|:---|
| code engine app | dockerfile | [code-engine-app](code-engine-app/README.md) | example application used for deploying into ibm cloud code engine |
| hello world | dockerfile | [hello-world](hello-world/README.md) | the "hello world" application invoked as an api endpoint |
| mcp gateway forge | template, dockerfile | [mcp-gateway-forge](mcp-gateway-forge/README.md) | Proxy and MCP Registry that federates MCP and REST services |
| qna rag chatbot | dockerfile | [qna_rag_chatbot](qna_rag_chatbot/README.md) | chatbot that can answer questions using RAG |
| ruby hello world | template | [ruby-hello-world](ruby-hello-world/README.md) | the "hello world" application written in ruby with web UI |
| wxo external agent| dockerfile | [wxo-external-agent](wxo-external-agent/README.md)| provides chat completions api that can be used as wxo external agent |

<sup> there is also limited support for "kube yaml" apps, similar to what regular helm chart wraps up (limited to plain kube core/v1 and apps/v1 resources etc), examples are not included here.</sup>
76 changes: 76 additions & 0 deletions code-engine-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Deploy code engine app to software hub dataplane

[code engine app](code-engine-handson-sample-app) is an example application used for deploying into ibm cloud code engine, the application interacts with ibm cloud object storage service, providing an UI interface for populating bucket created under object storage service. the same application can be deployed into software hub default dataplane as well

- before deploying this sample app, you would need to create object storage service in ibm cloud, create a test bucket and collect the following values:
```
BUCKETNAME : Bucket Name of IBM Object Storage
COS_ENDPOINT : ENDPOINT of IBM Object Storage, i.e. s3.<your ibm cloud region>.cloud-object-storage.appdomain.cloud
COS_APIKEY : API Key of IBM Object Storage, this is your ibm cloud api key that has access to object storage service
COS_RESOURCE_INSTANCE_ID : resource instance ID of IBM Object Storage, you may get the instance id from object store instance CRN, it is the UUID that starts after the last single colon and ends before the final double colon
TESTVALUE: of anything to write into object store bucket
```
- checkout the [pre-requisites](../README.md#pre-requisites-to-deploy-sample-applications) required before deploying this application into default dataplane

### Steps to deploy code-engine-app

1. Run `create-dockerfile-application` command inside the cpd-cli binary to deploy the app
2. Run `./cpd-cli manage create-dockerfile-application --help` to know more about other options available.
3. Run the create-dockerfile-application command
```
./cpd-cli manage create-dockerfile-application \
--instance_ns=zen \
--app_name=code-engine-app \
--app_port=3000 \
--tls_enabled=false \
--repo_url=https://github.com/IBM/swhub-custom-app-samples.git \
--repo_token=<YOUR GITHUB TOKEN> \
--repo_app_dir=code-engine-app/code-engine-handson-sample-app \
--app_envs='[{"name":"BUCKETNAME","value":"<your bucketname in ibm cloud>"},{"name":"TESTVALUE","value":"mytest"},{"name":"COS_ENDPOINT","value":"s3.<your ibm cloud region>.cloud-object-storage.appdomain.cloud"},{"name":"COS_APIKEY","value":"<your ibm api key>"},{"name":"COS_RESOURCE_INSTANCE_ID","value":"<your cos resource instance id>"},{"name":"HOME", "value":"/tmp"}]' \
--cpu=400m \
--memory=200Mi \
--cpu_limit=500m \
--memory_limit=400Mi
```
4. If you see this error in step 5 `-build` pod
```
Defaulted container "docker-build" out of: docker-build, git-clone (init), manage-dockerfile (init)
time="2025-10-30T23:58:57Z" level=info msg="Not using native diff for overlay, this may cause degraded performance for building images: kernel has CONFIG_OVERLAY_FS_REDIRECT_DIR enabled"
I1030 23:58:57.938443 1 defaults.go:112] Defaulting to storage driver "overlay" with options [mountopt=metacopy=on].
Caching blobs under "/var/cache/blobs".

Pulling image node:17.4 ...
Resolving "node" using unqualified-search registries (/var/run/configs/openshift.io/build-system/registries.conf)
Trying to pull registry.redhat.io/node:17.4...
Trying to pull registry.access.redhat.com/node:17.4...
Trying to pull quay.io/node:17.4...
Trying to pull docker.io/library/node:17.4...
time="2025-10-30T23:59:31Z" level=warning msg="Failed, retrying in 1s ... (1/3). Error: initializing source docker://node:17.4: reading manifest 17.4 in docker.io/library/node: toomanyrequests: You have reached your unauthenticated pull rate limit. https://www.docker.com/increase-rate-limit"`
```

Path the `pull-secret` with public docker username and password
```
# DOCKER_CONFIG=$(echo -n 'username:password' | base64 -w0)
oc set data secret/pull-secret -n openshift-config --from-literal=.dockerconfigjson="{\"auths\":{\"docker.io\":{\"auth\":\"$DOCKER_CONFIG\"}}}"
secret/pull-secret data updated
```

5. check pods in workload namespace

```
# oc get po -n wl
NAME READY STATUS RESTARTS AGE
final-code-engine-app-j5itik3ikksx-1-build 0/1 Completed 0 6m32s
final-code-engine-app-j5itik3ikksx-5f79744d79-75gpk 1/1 Running 0 3m49s
```

6. update application proxy config - copy `code-engine-app.conf.yaml` in this folder to `cpd-cli-workspace/olm-utils-workspace/work/`
```
./cpd-cli manage update-custom-application-proxy-config \
--instance_ns=zen \
--app_name=code-engine-app \
--app_run_id=<from create-dockerfile-application> \
--app_proxy_config_yaml=/tmp/work/code-engine-app.conf.yaml
```

7. Check the application running at `https://zen-route/physical_location/<default pl name>/<app_name>-<app_run_id>/`
37 changes: 37 additions & 0 deletions code-engine-app/code-engine-app.conf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
apiVersion: zen.cpd.ibm.com/v1
kind: ZenExtension
metadata:
name: {{ .serviceName }}
spec:
extensions: |
[
{
"extension_name": "{{ .serviceName }}",
"extension_type": "nginx",
"details": {
"upstream_conf": "upstream.conf",
"location_conf": "nginx.conf"
}
}
]
upstream.conf: |
upstream {{ .upstreamName }} {
keepalive 32;
keepalive_timeout 30s;
keepalive_requests 500;
server {{ .serviceName }}.{{ .dpPhyLocWorkloadNs }}.svc:{{ .servicePort }};
}
nginx.conf: |
location ~* /{{ .serviceName }}/(.*) {
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Connection "";
proxy_ssl_server_name on;
proxy_buffering off;
proxy_set_header If-Modified-Since "";
proxy_set_header If-None-Match "";
proxy_pass http://{{ .upstreamName }}/$1$is_args$args;
proxy_pass_header X-Accel-Buffering;
sub_filter_once off;
sub_filter '/info/' '/physical_location/{{ .zenPhysicalLocationName }}/{{ .serviceName }}/info/';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
104 changes: 104 additions & 0 deletions code-engine-app/code-engine-handson-sample-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# Next.js build output
.next

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port
12 changes: 12 additions & 0 deletions code-engine-app/code-engine-handson-sample-app/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM node:17.4

RUN apt-get -y update && apt-get -y upgrade

RUN apt-get remove -y --purge 'mysql-.*'

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY . .
RUN echo "now building..."
RUN npm install
CMD [ "npm", "start"]
14 changes: 14 additions & 0 deletions code-engine-app/code-engine-handson-sample-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# code-engine-handson-sample-app

This is a sample application for Code Engine Hanson.


### Environment Params

* BUCKETNAME : Bucket Name of IBM Object Storage
* TESTVALUE : A Config map Value
* COS_ENDPOINT : ENDPOINT of IBM Object Storage
* COS_APIKEY : API Key of IBM Object Storage
* COS_RESOURCE_INSTANCE_ID : resource instance ID of IBM Object Storage


39 changes: 39 additions & 0 deletions code-engine-app/code-engine-handson-sample-app/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var infoRouter = require('./routes/info');

var app = express();

// view engine setup

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.set("view engine", "html");
app.use('/', indexRouter);
app.use('/info', infoRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};

// render the error page
res.status(err.status || 500);
res.render('error');
});

module.exports = app;
Loading