openwhisk Documentation

Apache OpenWhisk is an open source serverless cloud platform

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy openwhisk on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name openwhisk -p 8080:8080 --restart always whisk/cache-invalidator-cosmosdb
Configured Services & Ports
โš™๏ธ cache-invalidator
image: whisk/cache-invalidator-cosmosdb
๐Ÿ”Œ Ports: 8080:8080
docker-compose.yml
yaml (docker-compose.yml)
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
---
version: '3'

networks:
  default:
    external:
      # Match the network name used by devtool docker compose setup
      name: openwhisk_default

services:
  cache-invalidator:
    image: whisk/cache-invalidator-cosmosdb
    ports:
      - "8080:8080"
    environment:
      - KAFKA_HOSTS=172.17.0.1:9093
      - COSMOSDB_ENDPOINT=${COSMOSDB_ENDPOINT}
      - COSMOSDB_KEY=${COSMOSDB_KEY}
      - COSMOSDB_NAME=${COSMOSDB_NAME}

1. Project Overview & Quickstart (apache/openwhisk)

File: README.md

OpenWhisk









OpenWhisk is a serverless functions platform for building cloud applications.
OpenWhisk offers a rich programming model for creating serverless APIs from functions,
composing functions into serverless workflows, and connecting events to functions using rules and triggers.
Learn more at http://openwhisk.apache.org.

Notice of Breaking Upgrade 10/17/2025

Apache Openwhisk has migrated to the Apache Pekko framework. The master branch as of 10/17/2025 uses Apache Pekko. This change results in a breaking change such that you must re-deploy new clusters and cutover traffic to the new cluster. All other changes should be transient to you other than instead of using Akka configuration overrides in your deployments, you would now need to update those to use the Pekko equivalent. A 3.x release branch will eventually follow this
change.

Quick Start

The easiest way to start using OpenWhisk is to install the "Standalone" OpenWhisk stack.
This is a full-featured OpenWhisk stack running as a Java process for convenience.
Serverless functions run within Docker containers. You will need Docker,
Java and Node.js available on your machine.

To get started:

text
git clone https://github.com/apache/openwhisk.git
cd openwhisk
./gradlew core:standalone:bootRun
  • When the OpenWhisk stack is up, it will open your browser to a functions Playground,
    typically served from http://localhost:3232. The Playground allows you create and run functions directly from your browser.

  • To make use of all OpenWhisk features, you will need the OpenWhisk command line tool called
    wsk which you can download from https://s.apache.org/openwhisk-cli-download.
    Please refer to the CLI configuration for additional details. Typically you
    configure the CLI for Standalone OpenWhisk as follows:

text
wsk property set \
  --apihost 'http://localhost:3233' \
  --auth '23bc46b1-71f6-4ed5-8c54-816aa4f8c502:123zO3xZCLrMN6v2BKK1dXYFpXlPkccOFqm12CdAsMgRU4VrNZ9lyGVCGuMDGIwP'
  • Standalone OpenWhisk can be configured to deploy additional capabilities when that is desirable.
    Additional resources are available here.

Deploy to Kubernetes

OpenWhisk can also be installed on a Kubernetes cluster. You can use
a managed Kubernetes cluster provisioned from a public cloud provider
(e.g., AKS, EKS, IKS, GKE), or a cluster you manage yourself.
Additionally for local development, OpenWhisk is compatible with Minikube,
and Kubernetes for Mac using the support built into Docker 18.06 (or higher).

To get started:

text
git clone https://github.com/apache/openwhisk-deploy-kube.git

Then follow the instructions in the OpenWhisk on Kubernetes README.md.

Learn Concepts and Commands

Browse the documentation to learn more. Here are some topics you may be
interested in:

OpenWhisk Community and Support

Report bugs, ask questions and request features here on GitHub.

You can also join the OpenWhisk Team on Slack https://openwhisk-team.slack.com and chat with developers. To get access to our public Slack team, request an invite https://openwhisk.apache.org/slack.html.

Project Repository Structure

The OpenWhisk system is built from a number of components. The picture below groups the components by their GitHub repos. Please open issues for a component against the appropriate repo (if in doubt just open against the main openwhisk repo).

What happens on an invocation?

This diagram depicts the steps which take place within Openwhisk when an action is invoked by the user:


File: ansible/README.md

Deploying OpenWhisk using Ansible

Getting started

If you want to deploy OpenWhisk locally using Ansible, you first need to install Ansible on your development environment:

Ubuntu users

shell script
sudo apt-get install python-pip
sudo pip install ansible==4.1.0
sudo pip install jinja2==3.0.1

Docker for Mac users

shell script
sudo easy_install pip
sudo pip install ansible==4.1.0
pip install jinja2==3.0.1

Docker for Mac does not provide any official ways to meet some requirements for OpenWhisk.
You need to depend on the workarounds until Docker provides official methods.

If you prefer Docker-machine to Docker for mac, you can follow instructions in docker-machine/README.md.

Enable Docker remote API

The remote Docker API is required for collecting logs using the Ansible playbook logs.yml.

Activate docker0 network (local dev only)

The OpenWhisk deployment via Ansible uses the docker0 network interface to deploy OpenWhisk and it does not exist on Docker for Mac environment.

An expedient workaround is to add alias for docker0 network to loopback interface.

shell script
sudo ifconfig lo0 alias 172.17.0.1/24

Using Ansible

Caveat: All Ansible commands are meant to be executed from the ansible directory.
This is important because that's where ansible.cfg is located which contains generic settings that are needed for the remaining steps.

Set the environment for the commands below by running

shell script
ENVIRONMENT=local  # or docker-machine or jenkins or vagrant

The default environment is local which works for Ubuntu and
Docker for Mac. To use the default environment, you may omit the -i parameter entirely. For older Mac installation using Docker Machine,
use -i environments/docker-machine.

In all instructions, replace <openwhisk_home> with the base directory of your OpenWhisk source tree. e.g. openwhisk

Ansible with pyenv (local dev only)

When using pyenv to manage your versions of python, the ansible python interpreter will use your system's default python, which may have a different version.

To make sure ansible uses the same version of python which you configured, execute:

bash
echo -e "\nansible_python_interpreter: `which python`\n" >> ./environments/local/group_vars/all

Preserving configuration and log directories on reboot

When using the local Ansible environment, configuration and log data is stored in /tmp by default. However, operating
system such as Linux and Mac clean the /tmp directory on reboot, resulting in failures when OpenWhisk tries to start
up again. To avoid this problem, export the OPENWHISK_TMP_DIR variable assigning it the path to a persistent
directory before deploying OpenWhisk.

Setup

This step should be executed once per development environment.
It will generate the hosts configuration file based on your environment settings.

This file is generated automatically for an ephemeral CouchDB instance during setup.yml.

The default configuration does not run multiple instances of core components (e.g., controller, invoker, kafka).
You may elect to enable high-availability (HA) mode by passing the Ansible option -e mode=HA when executing this playbook.
This will configure your deployment with multiple instances (e.g., two Kafka instances, and two invokers).

In addition to the host file generation, you need to configure the database for your deployment. This is done
by modifying the file ansible/db_local.ini to provide the following properties.

text
[db_creds]
db_provider=
db_username=
db_password=
db_protocol=
db_host=
db_port=

For convenience, you can use shell environment variables that are read by the playbook to generate the required db_local.ini file as shown below.

shell script
export OW_DB=CouchDB
export OW_DB_USERNAME=<your couchdb user>
export OW_DB_PASSWORD=<your couchdb password>
export OW_DB_PROTOCOL=<your couchdb protocol>
export OW_DB_HOST=<your couchdb host>
export OW_DB_PORT=<your couchdb port>

ansible-playbook -i environments/$ENVIRONMENT setup.yml

Use Cloudant as a datastore

shell script
export OW_DB=Cloudant
export OW_DB_USERNAME=<your cloudant user>
export OW_DB_PASSWORD=<your cloudant password>
export OW_DB_PROTOCOL=https
export OW_DB_HOST=<your cloudant user>.cloudant.com
export OW_DB_PORT=443

ansible-playbook -i environments/$ENVIRONMENT setup.yml

Install Prerequisites

This step is not required for local environments since all prerequisites are already installed, and therefore may be skipped.

This step needs to be done only once per target environment. It will install necessary prerequisites on all target hosts in the environment.

text
ansible-playbook -i environments/$ENVIRONMENT prereq.yml

Hint: During playbook execution the TASK [prereq : check for pip] can show as failed. This is normal if no pip is installed. The playbook will then move on and install pip on the target machines.

[Optional] Enable the new scheduler

You can enable the new scheduler of OpenWhisk.
It will run one more component called "scheduler" and ETCD.

Configure service providers for the scheduler

You can update service providers for the scheduler as follows.

common/scala/src/main/resources/reference.conf

If you are using ElasticSearch (recommended) then replace NoopDurationCheckerProvider with ElasticSearchDurationCheckerProvider below.

text
whisk.spi {
  ArtifactStoreProvider = org.apache.openwhisk.core.database.CouchDbStoreProvider
  ActivationStoreProvider = org.apache.openwhisk.core.database.ArtifactActivationStoreProvider
  MessagingProvider = org.apache.openwhisk.connector.kafka.KafkaMessagingProvider
  ContainerFactoryProvider = org.apache.openwhisk.core.containerpool.docker.DockerContainerFactoryProvider
  LogStoreProvider = org.apache.openwhisk.core.containerpool.logging.DockerToActivationLogStoreProvider
  LoadBalancerProvider = org.apache.openwhisk.core.loadBalancer.FPCPoolBalancer
  EntitlementSpiProvider = org.apache.openwhisk.core.entitlement.FPCEntitlementProvider
  AuthenticationDirectiveProvider = org.apache.openwhisk.core.controller.BasicAuthenticationDirective
  InvokerProvider = org.apache.openwhisk.core.invoker.FPCInvokerReactive
  InvokerServerProvider = org.apache.openwhisk.core.invoker.FPCInvokerServer
  DurationCheckerProvider = org.apache.openwhisk.core.scheduler.queue.NoopDurationCheckerProvider
}
.
.
.

Configure pause grace for the scheduler

Set the value of pause-grace to 10s by default

core/invoker/src/main/resources/application.conf

text
container-proxy {
    timeouts {
      # The "unusedTimeout" in the ContainerProxy,
      #aka 'How long should a container sit idle until we kill it?'
      idle-container = 10 minutes
      pause-grace = 10 seconds
      keeping-duration = 10 minutes
    }
  .
  .
  .

Disable the scheduler

  • You can disable the scheduler by configuring scheduler_enable.
  • The scheduler is enabled by default.

ansible/environments/local/group_vars/all

yaml
scheduler_enable: false

[Optional] Enable ElasticSearch Activation Store

When you use the new scheduler, it is recommended to use ElasticSearch as an activation store.

ansible/environments/local/group_vars

yaml
db_activation_backend: ElasticSearch
elastic_cluster_name: <your elasticsearch cluster name>
elastic_protocol: <your elasticsearch protocol>
elastic_index_pattern: <your elasticsearch index pattern>
elastic_base_volume: <your elasticsearch volume directory>
elastic_username: <your elasticsearch username>
elastic_password: <your elasticsearch username>

You can also refer to this guide to deploy OpenWhisk using ElasticSearch.

Deploying Using CouchDB

  • Make sure your db_local.ini file is setup for CouchDB then execute:
shell script
cd <openwhisk_home>
./gradlew distDocker
cd ansible
ansible-playbook -i environments/$ENVIRONMENT couchdb.yml
ansible-playbook -i environments/$ENVIRONMENT initdb.yml
ansible-playbook -i environments/$ENVIRONMENT wipe.yml
ansible-playbook -i environments/$ENVIRONMENT openwhisk.yml

# installs a catalog of public packages and actions
ansible-playbook -i environments/$ENVIRONMENT postdeploy.yml

# to use the API gateway
ansible-playbook -i environments/$ENVIRONMENT apigateway.yml
ansible-playbook -i environments/$ENVIRONMENT routemgmt.yml
  • You need to run initdb.yml every time you do a fresh deploy CouchDB to initialize the subjects database.
  • The wipe.yml playbook should be run on a fresh deployment only, otherwise actions and activations will be lost.
  • Run postdeploy.yml after deployment to install a catalog of useful packages.
  • To use the API Gateway, you'll need to run apigateway.yml and routemgmt.yml.
  • Use ansible-playbook -i environments/$ENVIRONMENT openwhisk.yml to avoid wiping the data store. This is useful to start OpenWhisk after restarting your Operating System.

Limitation

You cannot run multiple CouchDB nodes on a single machine. This limitation comes from Erlang EPMD which CouchDB relies on to find other nodes.
To deploy multiple CouchDB nodes, they should be placed on different machines respectively otherwise their ports will clash.

Deploying Using Cloudant

  • Make sure your db_local.ini file is set up for Cloudant. See Setup.
  • Then execute:
shell script
cd <openwhisk_home>
./gradlew distDocker
cd ansible
ansible-playbook -i environments/$ENVIRONMENT initdb.yml
ansible-playbook -i environments/$ENVIRONMENT wipe.yml
ansible-playbook -i environments/$ENVIRONMENT apigateway.yml
ansible-playbook -i environments/$ENVIRONMENT openwhisk.yml

# installs a catalog of public packages and actions
ansible-playbook -i environments/$ENVIRONMENT postdeploy.yml

# to use the API gateway
ansible-playbook -i environments/$ENVIRONMENT apigateway.yml
ansible-playbook -i environments/$ENVIRONMENT routemgmt.yml
  • You need to run initdb on Cloudant only once per Cloudant database to initialize the subjects database.
  • The initdb.yml playbook will only initialize your database if it is not initialized already, else it will skip initialization steps.
  • The wipe.yml playbook should be run on a fresh deployment only, otherwise actions and activations will be lost.
  • Run postdeploy.yml after deployment to install a catalog of useful packages.
  • To use the API Gateway, you'll need to run apigateway.yml and routemgmt.yml.
  • Use ansible-playbook -i environments/$ENVIRONMENT openwhisk.yml to avoid wiping the data store. This is useful to start OpenWhisk after restarting your Operating System.

Deploying Using MongoDB

You can choose MongoDB instead of CouchDB as the database backend to store entities.

  • Deploy a mongodb server(Optional, for test and develop only, use an external MongoDB server in production).
    You need to execute pip install pymongo first
text
ansible-playbook -i environments/<environment> mongodb.yml -e mongodb_data_volume="/tmp/mongo-data"
  • Then execute
text
cd <openwhisk_home>
./gradlew distDocker
cd ansible
ansible-playbook -i environments/<environment> initMongodb.yml -e mongodb_connect_string="mongodb://172.17.0.1:27017"
ansible-playbook -i environments/<environment> apigateway.yml -e mongodb_connect_string="mongodb://172.17.0.1:27017"
ansible-playbook -i environments/<environment> openwhisk.yml -e mongodb_connect_string="mongodb://172.17.0.1:27017" -e db_artifact_backend="MongoDB"

# installs a catalog of public packages and actions
ansible-playbook -i environments/<environment> postdeploy.yml

# to use the API gateway
ansible-playbook -i environments/<environment> apigateway.yml
ansible-playbook -i environments/<environment> routemgmt.yml

Available parameters for ansible are

text
mongodb:
    connect_string: "{{ mongodb_connect_string }}"
    database: "{{ mongodb_database | default('whisks') }}"
    data_volume: "{{ mongodb_data_volume | default('mongo-data') }}"

Using ElasticSearch to Store Activations

You can use ElasticSearch (ES) to store activations separately while other entities remain stored in CouchDB. There is an Ansible playbook to setup a simple ES cluster for testing and development purposes.

  • Provide your custom ES related ansible arguments:
text
elastic_protocol="http"
elastic_index_pattern="openwhisk-%s" // this will be combined with namespace's name, so different namespace can use different index
elastic_base_volume="esdata" // name of docker volume to store ES data
elastic_cluster_name="openwhisk"
elastic_java_opts="-Xms1g -Xmx1g"
elastic_loglevel="INFO"
elastic_username="admin"
elastic_password="admin"
elasticsearch_connect_string="x.x.x.x:9200,y.y.y.y:9200" // if you want to use an external ES cluster, add it
  • Then execute:
shell script
cd <openwhisk_home>
./gradlew distDocker
cd ansible
# couchdb is still needed to store subjects and actions
ansible-playbook -i environments/$ENVIRONMENT couchdb.yml
ansible-playbook -i environments/$ENVIRONMENT initdb.yml
ansible-playbook -i environments/$ENVIRONMENT wipe.yml
# this will deploy a simple ES cluster, you can skip this to use external ES cluster
ansible-playbook -i environments/$ENVIRONMENT elasticsearch.yml
ansible-playbook -i environments/$ENVIRONMENT openwhisk.yml -e db_activation_backend=ElasticSearch

# installs a catalog of public packages and actions
ansible-playbook -i environments/$ENVIRONMENT postdeploy.yml

# to use the API gateway
ansible-playbook -i environments/$ENVIRONMENT apigateway.yml
ansible-playbook -i environments/$ENVIRONMENT routemgmt.yml

Configuring the installation of `wsk` CLI

There are two installation modes to install wsk CLI: remote and local.

The mode "remote" means to download the wsk binaries from available web links.
By default, OpenWhisk sets the installation mode to remote and downloads the
binaries from the CLI
release page,
where OpenWhisk publishes the official wsk binaries.

The mode "local" means to build and install the wsk binaries from local CLI
project. You can download the source code of OpenWhisk CLI
here.
Let's assume your OpenWhisk CLI home directory is
$OPENWHISK_HOME/../openwhisk-cli and you've already exported
OPENWHISK_HOME to be the root directory of this project. After you download
the CLI repository, use the gradle command to build the binaries (you can omit
the -PnativeBuild if you want to cross-compile for all supported platforms):

shell script
cd "$OPENWHISK_HOME/../openwhisk-cli"
./gradlew releaseBinaries -PnativeBuild

The binaries are generated and put into a tarball in the folder
../openwhisk-cli/release. Then, use the following Ansible command
to (re-)configure the CLI installation:

shell script
export OPENWHISK_ENVIRONMENT=local  # ... or whatever
ansible-playbook -i environments/$OPENWHISK_ENVIRONMENT edge.yml -e mode=clean
ansible-playbook -i environments/$OPENWHISK_ENVIRONMENT edge.yml \
    -e cli_installation_mode=local \
    -e openwhisk_cli_home="$OPENWHISK_HOME/../openwhisk-cli"

The parameter cli_installation_mode specifies the CLI installation mode and
the parameter openwhisk_cli_home specifies the home directory of your local
OpenWhisk CLI. (n.b. openwhisk_cli_home defaults to
$OPENWHISK_HOME/../openwhisk-cli.)

Once the CLI is installed, you can use it to work with Whisk.

Hot-swapping a Single Component

The playbook structure allows you to clean, deploy or re-deploy a single component as well as the entire OpenWhisk stack. Let's assume you have deployed the entire stack using the openwhisk.yml playbook. You then make a change to a single component, for example the invoker. You will probably want a new tag on the invoker image so you first build it using:

shell script
cd <openwhisk_home>
./gradlew :core:invoker:distDocker -PdockerImageTag=myNewInvoker

Then all you need to do is re-deploy the invoker using the new image:

shell script
cd ansible
ansible-playbook -i environments/$ENVIRONMENT invoker.yml -e docker_image_tag=myNewInvoker

Hint: You can omit the Docker image tag parameters in which case latest will be used implicitly.

Cleaning a Single Component

You can remove a single component just as you would remove the entire deployment stack.
For example, if you wanted to remove only the controller you would run:

shell script
cd ansible
ansible-playbook -i environments/$ENVIRONMENT controller.yml -e mode=clean

Caveat: In distributed environments some components (e.g. Invoker, etc.) exist on multiple machines. So if you run a playbook to clean or deploy those components, it will run on all of the hosts targeted by the component's playbook.

Cleaning an OpenWhisk Deployment

Once you are done with the deployment you can clean it from the target environment.

shell script
ansible-playbook -i environments/$ENVIRONMENT openwhisk.yml -e mode=clean

Removing all prereqs from an environment

This is usually not necessary, however in case you want to uninstall all prereqs from a target environment, execute:

shell script
ansible-playbook -i environments/$ENVIRONMENT prereq.yml -e mode=clean

Lean Setup

To have a lean setup (no Kafka, Zookeeper and no Invokers as separate entities):

At Deploying Using CouchDB step, replace:

shell script
ansible-playbook -i environments/$ENVIRONMENT openwhisk.yml

by:

shell script
ansible-playbook -i environments/$ENVIRONMENT openwhisk.yml -e lean=true

Troubleshooting

Some of the more common problems and their solution are listed here.

Setuptools Version Mismatch

If you encounter the following error message during ansible execution

text
ERROR! Unexpected Exception: ... Requirement.parse('setuptools>=11.3'))

your setuptools package is likely out of date. You can upgrade the package using this command:

shell script
pip install --upgrade setuptools --user python

Mac Setup - Python Interpreter

The MacOS environment assumes Python is installed in /usr/local/bin which is the default location when using brew.
The following error will occur if Python is located elsewhere:

text
ansible all -i environments/mac -m ping
ansible | FAILED! => {
    "changed": false,
    "failed": true,
    "module_stderr": "/bin/sh: /usr/local/bin/python: No such file or directory\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE",
    "parsed": false
}

An expedient workaround is to create a link to the expected location:

shell script
ln -s $(which python) /usr/local/bin/python

Alternatively, you can also configure the location of Python interpreter in environments/<environment>/group_vars.

shell script
ansible_python_interpreter: "/usr/local/bin/python"

Failed to import docker-py

After brew install ansible, the following lines are printed out:

text
==> Caveats
If you need Python to find the installed site-packages:
  mkdir -p ~/Library/Python/2.7/lib/python/site-packages
  echo '/usr/local/lib/python2.7/site-packages' > ~/Library/Python/2.7/lib/python/site-packages/homebrew.pth

Just run the two commands to fix this issue.

Spaces in Paths

Ansible 2.1.0.0 and earlier versions do not support a space in file paths.
Many file imports and roles will not work correctly when included from a path that contains spaces.
If you encounter this error message during Ansible execution

text
fatal: [ansible]: FAILED! => {"failed": true, "msg": "need more than 1 value to unpack"}

the path to your OpenWhisk ansible directory contains spaces. To fix this, please copy the source tree to a path
without spaces as there is no current fix available to this problem.

Changing limits

The default system throttling limits are configured in this file ./group_vars/all and may be changed by modifying the group_vars for your specific environment.

text
limits:
  invocationsPerMinute: "{{ limit_invocations_per_minute | default(60) }}"
  concurrentInvocations: "{{ limit_invocations_concurrent | default(30) }}"
  firesPerMinute: "{{ limit_fires_per_minute | default(60) }}"
  sequenceMaxLength: "{{ limit_sequence_max_length | default(50) }}"
  • The limits.invocationsPerMinute represents the allowed namespace action invocations per minute.
  • The limits.concurrentInvocations represents the maximum concurrent invocations allowed per namespace.
  • The limits.firesPerMinute represents the allowed namespace trigger firings per minute.
  • The limits.sequenceMaxLength represents the maximum length of a sequence action.

Set the timezone for containers

The default timezone for all system containers is UTC. The timezone may differ from your servers which could make it difficult to inspect logs. The timezone is configured globally in group_vars/all or by passing an extra variable -e docker_timezone=xxx when you run an ansible-playbook.


File: core/standalone/README.md

OpenWhisk Standalone Server

OpenWhisk standalone server is meant to run a simple OpenWhisk server for local development and test purposes. It can be
executed as a normal java application from command line.

bash
java -jar openwhisk-standalone.jar

This should start the OpenWhisk server on port 3233 by default and launch a Playground UI at port 3232.

The Playground UI can be used to try out simple actions. To make use of all OpenWhisk features configure the cli and
then try out the samples.

This server by default uses a memory based store and does not depend on any other external service like Kafka and CouchDB.
It only needs Docker and Java to for running.

Few key points related to it

  • Uses in memory store. Once the server is stopped all changes would be lost
  • Bootstraps the guest and whisk.system with default keys
  • Supports running on MacOS, Linux and Windows (experimental) setup
  • Can be customized to use any other storage like CouchDB

Build

To build this standalone server run

bash
$ ./gradlew :core:standalone:build

This would create the runnable jar in bin/ directory. If you directly want to run the
server then you can use following command

bash
$ ./gradlew :core:standalone:bootRun

To pass argument to the run command use

bash
$ ./gradlew :core:standalone:bootRun --args='-m runtimes.json'

You can also build a standalone docker image with:

bash
$ ./gradlew :core:standalone:distDocker

Usage

OpenWhisk standalone server support various launch options

text
/* Detailed source-code truncated for AI context efficiency. */

Sections below would illustrate some of the supported options

To change the default config you can provide a custom application.conf file via -c option. The application conf file
must always include the default standalone.conf

hocon
include classpath("standalone.conf")

whisk {
  //Custom config
}

Then pass this config file

bash
java -jar openwhisk-standalone.jar -c custom.conf

Adding custom namespaces

If you need to register custom namespaces (aka users) then you can pass them via config file like below

hocon
include classpath("standalone.conf")

whisk {
  users {
    whisk-test = "cafebabe-cafe-babe-cafe-babecafebabe:007zO3xZCLrMN6v2BKK1dXYFpXlPkccOFqm12CdAsMgRU4VrNZ9lyGVCGuMDGIwP"
  }
}

Then pass this config file via -c option. You can check the users created from log

text
[2019-06-21T19:52:02.923Z] [INFO] [#tid_userBootstrap] [StandaloneOpenWhisk] Created user [guest]
[2019-06-21T19:52:03.008Z] [INFO] [#tid_userBootstrap] [StandaloneOpenWhisk] Created user [whisk.system]
[2019-06-21T19:52:03.094Z] [INFO] [#tid_userBootstrap] [StandaloneOpenWhisk] Created user [whisk.test]

Using custom runtimes

To use custom runtime pass the runtime manifest via -m option

json
{
  "runtimes": {
    "ruby": [
      {
        "kind": "ruby:2.5",
        "default": true,
        "deprecated": false,
        "attached": {
          "attachmentName": "codefile",
          "attachmentType": "text/plain"
        },
        "image": {
          "prefix": "openwhisk",
          "name": "action-ruby-v2.5",
          "tag": "latest"
        }
      }
    ]
  }
}

The pass this file at launch time

bash
java -jar openwhisk-standalone.jar -m custom-runtime.json

You can then see the runtime config reflect in http://localhost:3233

Using CouchDB

If you need to use CouchDB then you can launch the standalone server with --couchdb option. This would launch
a CouchDB server which would configured to store files in user home directory under .openwhisk/standalone folder.

If you need to connect to external CouchDB or any other supported artifact store then you can pass the required config

hocon
include classpath("standalone.conf")

whisk {
  couchdb {
    protocol = "http"
    host = "172.17.0.1"
    port = "5984"
    username = "whisk_admin"
    password = "some_passw0rd"
    provider = "CouchDB"
    databases {
      WhiskAuth = "whisk_local_subjects"
      WhiskEntity = "whisk_local_whisks"
      WhiskActivation = "whisk_local_activations"
    }
  }
}

Then pass this config file via -c option.

Note that Standalone OpenWhisk will not bootstrap users and actions (e.g., API Gateway and Playground UI)
when using an external database unless explicitly requested with --enable-bootstrap. This is to ensure
that default users and actions are not added to your external artifact store.

Using API Gateway

API Gateway mode can be enabled via --api-gw flag. In this mode upon launch a separate container for OpenWhisk API gateway
would be launched on port 3234 (can be changed with --api-gw-port). In this mode you can make use of the
API Gateway support.

Using Kafka

Standalone OpenWhisk supports launching an embedded kafka. This mode is mostly useful for developers working on OpenWhisk
implementation itself.

text
java -jar openwhisk-standalone.jar --kafka

It also supports launching a Kafka UI based on Kafdrop 3 which enables seeing the topics created and structure of messages
exchanged on those topics.

text
java -jar openwhisk-standalone.jar --kafka --kafka-ui

By default the ui server would be accessible at http://localhost:9000. In case 9000 port is busy then a random port would
be selected. To find out the port look for message in log like below (or grep for whisk-kafka-drop-ui)

text
[ 9092  ] localhost:9092 (kafka)
[ 9092  ] 192.168.65.2:9091 (kafka-docker)
[ 2181  ] Zookeeper (zookeeper)
[ 9000  ] http://localhost:9000 (whisk-kafka-drop-ui)

User Events

Standalone OpenWhisk supports emitting user events and displaying them via Grafana Dashboard. The metrics are
consumed by User Event Service which converts them into metrics consumed via Prometheus.

text
java -jar openwhisk-standalone.jar --user-events

This mode would launch an embedded Kafka, User Event service, Prometheus and Grafana with preconfigured dashboards.

text
Launched service details

[ 9092  ] localhost:9092 (kafka)
[ 9091  ] 192.168.65.2:9091 (kafka-docker)
[ 2181  ] Zookeeper (zookeeper)
[ 3235  ] http://localhost:3235 (whisk-user-events)
[ 9090  ] http://localhost:9090 (whisk-prometheus)
[ 3000  ] http://localhost:3000 (whisk-grafana)

Using KubernetesContainerFactory

Standalone OpenWhisk can be configured to use KubernetesContainerFactory (KCF) via --dev-kcf option. This mode can be used to
simplify developing KubernetesContainerFactory.

Below mentioned steps are based on Kind tool for running local Kubernetes clusters using Docker container "nodes".
However this mode should work against any Kubernetes cluster if the the KUBECONFIG is properly set.

1. Install and configure Kind

We would use Kind to setup a local k8s. Follow the steps here to create a simple cluster.

bash
$ kind create cluster --wait 5m

# Export the kind config for kubectl usage
$ export KUBECONFIG="$(kind get kubeconfig-path)"

# Configure the default namespace
$ kubectl config set-context --current --namespace=default

# See the config path
$ kind get kubeconfig-path
/Users/example/.kube/kind-config-kind

2. Launch Standalone

bash
# Launch it with `kubeconfig` system property set to kind config
$ java  -Dkubeconfig="$(kind get kubeconfig-path)" -jar bin/openwhisk-standalone.jar --dev-kcf

Once started and required .wskprops configured to use the standalone server create a hello.js function

js
function main(params) {
    greeting = 'hello, world'
    var hello = {payload: greeting}
    var result = {...hello, ...process.env}
    console.log(greeting);
    return result
}
bash
$ wsk action create hello hello.js
$ wsk action invoke hello -br

This shows an output like below indicating that KubernetesContainerFactory based invocation is working properly.

text
{
    "HOME": "/root",
    "HOSTNAME": "wsk0-2-prewarm-nodejs10",
    "KUBERNETES_PORT": "tcp://10.96.0.1:443",
    "KUBERNETES_PORT_443_TCP": "tcp://10.96.0.1:443",
    "KUBERNETES_PORT_443_TCP_ADDR": "10.96.0.1",
    "KUBERNETES_PORT_443_TCP_PORT": "443",
    "KUBERNETES_PORT_443_TCP_PROTO": "tcp",
    "KUBERNETES_SERVICE_HOST": "10.96.0.1",
    "KUBERNETES_SERVICE_PORT": "443",
    "KUBERNETES_SERVICE_PORT_HTTPS": "443",
    "NODE_VERSION": "10.15.3",
    "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "PWD": "/nodejsAction",
    "YARN_VERSION": "1.13.0",
    "__OW_ACTION_NAME": "/guest/hello",
    "__OW_ACTION_VERSION": "0.0.1",
    "__OW_ACTIVATION_ID": "71e48d2d62e142eca48d2d62e192ec2d",
    "__OW_API_HOST": "http://host.docker.internal:3233",
    "__OW_DEADLINE": "1570223213407",
    "__OW_NAMESPACE": "guest",
    "__OW_TRANSACTION_ID": "iSOoNklk6V7l7eh8KJnvugidKEmaNJmv",
    "payload": "hello, world"
}

Launching OpenWhisk standalone with Docker

If you have docker and bash installed, you can launch the standalone openwhisk from the docker image with just:

bash <(curl -sL https://s.apache.org/openwhisk.sh)

The script will start the standalone controller with Docker, and will also try to open the playground. It was tested on Linux, OSX and Windows with Git Bash. If a browser does not automatically open the OpenWhisk playground, you can access it at http://localhost:3232.

The default standalone controller image is published as openwhisk/standalone:nightly for convenience.

If you do not want to execute arbitrary code straight from the net, you can look at this script, check it and run it when you feel safe.

If the playground is not enough, you can then install the wsk CLI and retrieve the command line to configure wsk with:

docker logs openwhisk | grep 'wsk property'

To properly shut down OpenWhisk and any additional containers it has created, use this script or run the command:

docker exec openwhisk stop

Extra Args for the Standalone OpenWhisk Docker Image

You can specify a different image to this script and/or pass additional parameters to Docker and/or to the standalone jar. The general format is:

bash <(curl -sL https://s.apache.org/openwhisk.sh) [<docker-parameters>...] [] [<standalone-jar-options>...]

e.g.

bash <(curl -sL https://s.apache.org/openwhisk.sh) -e SOME_DOCKER_ENV=a openwhisk/standalone:nightly --no-ui

Extra args are useful to configure the JVM running OpenWhisk and to propagate additional environment variables to containers running images. This feature is useful for example to enable debugging for actions.

You can pass additional parameters (for example set system properties) to the JVM running OpenWhisk setting the environment variable JVM_EXTRA_ARGS. For example -e JVM_EXTRA_ARGS=-Dconfig.loads allows to enable tracing of configuration. You can set any OpenWhisk parameter with this feature.

You can also set additional environment variables for each container running actions invoked by OpenWhisk by setting CONTAINER_EXTRA_ENV. For example, setting -e CONTAINER_EXTRA_ENV=__OW_DEBUG_PORT=8081 enables debugging for those images supporting starting the action under a debugger, like the typescript runtime.


File: core/monitoring/user-events/README.md

OpenWhisk User Events

This service connects to events topic and publishes the events to various services like Prometheus, Datadog etc via Kamon. Refer to user specific metrics on how to enable them.

Local Run

First configure and run openwhisk docker-compose that can be found in the openwhisk-tools project.

  • Start service inside the cluster (on the same docker-compose network: openwhisk_default)
  • The service will be available on port 9095
  • The endpoint for exposing the metrics for Prometheus can be found on /metrics.

Usage

The service needs the following env variables to be set

  • KAFKA_HOSTS - For local env it can be set to 172.17.0.1:9093. When using OpenWhisk Devtools based setup use kafka
  • Namespaces can be removed from reports by listing them inside the reference.conf using the whisk.user-events.ignored-namespaces configuration.
    e.g:
text
whisk {
  user-events {
    ignored-namespaces = ["canary","testing"]
  }
}
  • To rename metrics tags, use the below configuration. Currently, this configuration only applies to the Prometheus
    Metrics. For example, here namespace tag name will be replaced by ow_namespace in all metrics.
text
whisk {
  user-events {
    rename-tags {
      # rename/relabel prometheus metrics tags
      "namespace" = "ow_namespae"
     }
  }
}

Integrations

Prometheus

The docker container would run the service and expose the metrics in format required by Prometheus at 9095 port

Grafana

The Openwhisk - Action Performance Metrics Grafana4 dashboard is available on localhost port 3000 at this address:
http://localhost:3000/d/Oew1lvymk/openwhisk-action-performance-metrics

The latest version of the dashboard can be found in the "compose/dashboard/openwhisk_events.json"


File: core/cosmosdb/cache-invalidator/README.md

OpenWhisk Cache Invalidator Service

This service performs cache invalidation in an OpenWhisk cluster to enable cache event propagation in multi region setups.

Design

An OpenWhisk cluster uses a Kafka topic cacheInvalidation to communicate changes to any cached entity. Messages on this
topic are of the form

json
{"instanceId":"controller0","key":{"mainId":"guest/hello"}}

When deploying OpenWhisk across multiple nodes which do not share a common Kafka instance, we need a way to propagate the
cache-change events across the cluster. For CosmosDB based setups this can be done by using CosmosDB ChangeFeed
support. It enables reading changes that are made to any specific collection.

This service makes use of change feed processor java library and listen to changes happening in whisks and subject
collections and then convert them into Kafka message events which can be sent to cacheInvalidation topic local to the cluster

Usage

The service needs following env variables to be set

  • KAFKA_HOSTS - For local env it can be set to 172.17.0.1:9093. When using OpenWhisk Devtools based setup use kafka
  • COSMOSDB_ENDPOINT - Endpoint URL like https://.documents.azure.com:443/
  • COSMOSDB_KEY - DB Key
  • COSMOSDB_NAME - DB name

Upon startup it would create a collection to manage the lease data with name cache-invalidator-lease. For events sent by
this service instanceId are sent to cache-invalidator

Local Run

Setup the OpenWhisk cluster using devtools but have it connect to CosmosDB. This would also start
the Kafka Topic UI at port 8001. Then when changes are made to the database, you should see events sent to the Kafka
topic. For example, if a a package is created with wsk package create test-package using the guest account, the following
event is generated:

json
{"instanceId":"cache-invalidator","key":{"mainId":"guest/test-package"}}

File: docs/dev/troubleshooting/build-failures.md

Build Failures

This guide details problems that may occur during the OpenWhisk build process.

Dependency download failures from JCenter

Occasionally build failures occur when the JCenter repository is experiencing problems. An example of such a failure
is shown below.

text
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring root project 'openwhisk'.
> Could not resolve all files for configuration ':classpath'.
   > Could not download groovy-all.jar (org.codehaus.groovy:groovy-all:2.4.7)
      > Could not get resource 'https://jcenter.bintray.com/org/codehaus/groovy/groovy-all/2.4.7/groovy-all-2.4.7.jar'.
         > Could not GET 'https://jcenter.bintray.com/org/codehaus/groovy/groovy-all/2.4.7/groovy-all-2.4.7.jar'.
            > Connect to akamai.bintray.com:443 [akamai.bintray.com/23.45.134.89] failed: Connection timed out (Connection timed out)

To determine if this error is indeed related to JCenter issues, check the JFrog Bintray
status page.


File: docs/dev/configuration.md

Scala component configuration

Our Scala components are in the process of switching from our own WhiskConfig to the TypesafeConfig based pureconfig. That will give us a more sane way of parsing environment values, overriding them and defining sensible defaults for them.

TypesafeConfig is able to override its values via JVM system properties. Unfortunately, docker only supports passing environment variables in a comfortable way.

To solve that mismatch, we use a script to transform environment variables into JVM system properties to spare the developer of manually overriding all the values via explicit environment -> TypesafeConfig value mapping. That script applies the following transformations to all environment variables starting with a defined prefix ("CONFIG_" in our case):

  • _ becomes . (TypesafeConfig hierarchies are built using .)
  • camelCased becomes camel-cased (Kebabcase is usually used for TypesafeConfig keys)
  • PascalCased stays PascalCased (Defining classnames for overriding SPIs is crucial)

Examples:

  • CONFIG_whisk_loadbalancer_invokerBusyThreshold becomes -Dwhisk.loadbalancer.invoker-busy-threshold
  • CONFIG_pekko_remote_netty_tcp_bindPort becomes -Dpekko.remote.netty.tcp.bind-port
  • CONFIG_whisk_spi_LogStoreProvider becomes -Dwhisk.spi.LogStoreProvider

File: docs/dev/future.md

Potential Future Enhancements

Web actions potential future enhancements

It is worthwhile to consider how to make several of the features currently offered by web actions more generally available to all action. It may also be useful to generalize the web-export annotation to provide additional control over which HTTP methods an action is prepared the handle and similarly which content types it supports. One can imagine doing this with a richer web-export annotation which may define at least these additional properties:

  1. methods: array of HTTP methods accepted.
  2. extensions: array of supported extensions.
  3. authentication: one of {"none", "builtin"} where none is for anonymous access and builtin for OpenWhisk authentication.

As in -a web-export '{ "methods": ["get", "post"], "extensions": ["http"], "authentication": "none" }' for a web action that only accepts get and post requests, handled .http extensions only, and permits anonymous access. A richer set of annotations will allow the controller to reject requests early if a web action does not support a particular method for example. The current implementation will accept get, post, put and delete HTTP methods without discrimination for any web action.


File: docs/dev/modules.md

Modules

Main

| Module | Description | Module Status |
|--- |--- |--- |
| openwhisk | Apache OpenWhisk is an open source serverless cloud platform | |
| openwhisk-apigateway | Apache OpenWhisk API Gateway service for exposing actions as REST interfaces. | |
| openwhisk-catalog | Curated catalog of Apache OpenWhisk packages to interface with event producers and consumers | |
| openwhisk-cli | Apache OpenWhisk Command Line Interface (CLI) | |
| openwhisk-composer | Apache OpenWhisk Composer provides a high-level programming model in JavaScript for composing serverless functions | |
| openwhisk-composer-python | Apache OpenWhisk Composer Python provides a high-level programming model in Python for composing serverless functions | |
| openwhisk-wskdeploy | Apache OpenWhisk utility for deploying and managing OpenWhisk projects and packages | |

Clients

| Module | Description | Module Status |
|--- |--- |--- |
| openwhisk-client-go | Go client library for the Apache OpenWhisk platform | |
| openwhisk-client-js | JavaScript client library for the Apache OpenWhisk platform | |

Runtimes

| Module | Description | Module Status |
|--- |--- |--- |
| openwhisk-runtime-deno | Apache OpenWhisk Runtime Deno supports Apache OpenWhisk functions written in Deno | |
| openwhisk-runtime-docker | Apache OpenWhisk SDK for building Docker "blackbox" runtimes | |
| openwhisk-runtime-dotnet | Apache OpenWhisk Runtime .Net supports Apache OpenWhisk functions written in .Net languages | |
| openwhisk-runtime-go | Apache OpenWhisk Runtime Go supports Apache OpenWhisk functions written in Go | |
| openwhisk-runtime-java | Apache OpenWhisk Runtime Java supports Apache OpenWhisk functions written in Java and other JVM-hosted languages | |
| openwhisk-runtime-nodejs | Apache OpenWhisk Runtime NodeJS supports Apache OpenWhisk functions written in JavaScript for NodeJS | |
| openwhisk-runtime-php | Apache OpenWhisk Runtime PHP supports Apache OpenWhisk functions written in PHP | |
| openwhisk-runtime-python | Apache OpenWhisk Runtime Python supports Apache OpenWhisk functions written in Python | |
| openwhisk-runtime-ruby | Apache OpenWhisk Runtime Ruby supports Apache OpenWhisk functions written in Ruby | |
| openwhisk-runtime-rust | Apache OpenWhisk Runtime Rust supports Apache OpenWhisk functions written in Rust | |
| openwhisk-runtime-swift | Apache OpenWhisk Runtime Swift supports Apache OpenWhisk functions written in Swift | |

Deployments

| Module | Description | Module Status |
|--- |--- |--- |
| openwhisk-deploy-kube | The Apache OpenWhisk Kubernetes Deployment repository supports deploying the Apache OpenWhisk system on Kubernetes and OpenShift clusters. | |

Packages

| Module | Description | Module Status |
|--- |--- |--- |
| openwhisk-package-alarms | Apache OpenWhisk package that can be used to create periodic, time-based alarms. | |
| openwhisk-package-cloudant | The Apache OpenWhisk cloudant package enables you to work with a Cloudant/CouchDB database | |
| openwhisk-package-deploy | Apache openwhisk | |
| openwhisk-package-kafka | Apache OpenWhisk package for communicating with Kafka or Message Hub | |
| openwhisk-package-pushnotifications | OpenWhisk Package for Bluemix Push Notifications Service | |
| openwhisk-pluggable-provider | Apache OpenWhisk pluggable trigger feed event provider | |

Samples and Examples

| Module | Description |
|--- |--- |
| openwhisk-slackinvite | Invite for Apache OpenWhisk Team on Slack |

Development Tools

| Module | Description |
|--- |--- |
| openwhisk-devtools | Development tools for building and deploying Apache OpenWhisk |
| openwhisk-intellij-plugin | Intellij plugin for Apache OpenWhisk |
| openwhisk-vscode-extension | VSCode extension for Apache OpenWhisk |
| openwhisk-wskdebug | Debugging and live development tool for Apache OpenWhisk |

Utilities

| Module | Description |
|--- |--- |
| openwhisk-release | Tools and documentation for Apache OpenWhisk Release Managers |
| openwhisk-utilities | Shared utilities used across Apache OpenWhisk project repositories. |

Others

| Module | Description |
|--- |--- |
| openwhisk-test | Test repo. for Apache OpenWhisk client-side tooling. |
| openwhisk-website | Apache OpenWhisk website (openwhisk.apache.org) content; built using Jekyll |

Archived

| Module | Description |
|--- |--- |
| openwhisk-GitHubSlackBot | [DEPRECATED] - Demonstration of integration of GitHub Pull Request management with Slack and using Alarms |
| openwhisk-client-python | [DEPRECATED] - REST API of OpenWhisk can be used directly from Python |
| openwhisk-client-swift | [DEPRECATED] - openwhisk-client-swift is a Swift client SDK for OpenWhisk with support for iOS, WatchOS2, and Darwin CLI apps |
| openwhisk-debugger | [DEPRECATED] - The OpenWhisk debugger project |
| openwhisk-deploy-mesos | Apache OpenWhisk deployment scripts and configuration files for running under Apache Mesos. |
| openwhisk-deploy-openshift | [DEPRECATED] - This project can be used to deploy Apache OpenWhisk to the OpenShift platform |
| openwhisk-external-resources | โœจ Curated list of awesome OpenWhisk things โœจ |
| openwhisk-package-jira | [DEPRECATED] - Interact with JIRA software software development tool used for issue tracking, and project management functions |
| openwhisk-package-rss | [DEPRECATED] - RSS feed package |
| openwhisk-package-template | [DEPRECATED] - This is a template to be use when creating new packages for OpenWhisk |
| openwhisk-playground | [DEPRECATED] - This library provides functionality of executing a snippet of source code as OpenWhisk action for OpenWhisk Xcode Source Editor Extension |
| openwhisk-podspecs | [DEPRECATED] - CocoaPods Podspecs repo for openwhisk-client-swift |
| openwhisk-runtime-ballerina | Apache OpenWhisk Runtime Ballerina supports Apache OpenWhisk functions written in Ballerina |
| openwhisk-sample-matos | [DEPRECATED] - sample application with Message Hub and Object Store |
| openwhisk-sample-slackbot | [DEPRECATED] - A proof-of-concept Slackbot to invoke OpenWhisk actions. |
| openwhisk-selfserve-test | [DEPRECATED] - Apache openwhisk |
| openwhisk-tutorial | [DEPRECATED] - An interactive learning environment for the Apache OpenWhisk command line |
| openwhisk-vscode | [DEPRECATED] - Visual Studio Code extension (prototype) for authoring OpenWhisk actions inside the editor. |
| openwhisk-workshop | [DEPRECATED] - OpenWhisk workshop to help developers learn how to build serverless applications using the platform. |
| openwhisk-xcode | [DEPRECATED] - Collection of OpenWhisk tools for OS X implemented in Swift 3. |


File: docs/images/README.md

This folder contains approved OpenWhisk logo images bearing the Trademark (TM) symbol that indicates that the OpenWhisk project has been granted (or has filed for) a trademark for the OpenWhisk name and/or logo in various geographies.

2. Official Technical Reference & Guides (apache/openwhisk-website)

Apache OpenWhisk Website


Apache OpenWhisk is a cloud-first distributed event-based programming service. It provides a programming model to upload event handlers to a cloud service, and register the handlers to respond to various events.

Quickstart for Local Development

Install Prerequisites

sh
# Verify Node and Node Package Manager are installed
node -v
npm -v

# Verify Ruby is installed
ruby -v

# Install Jekyll, which is used to build the site
gem install jekyll bundler

Clone and start development server

sh
# Clone the repository (and correct branch).
git clone https://github.com/apache/openwhisk-website.git

# Move into the cloned repo.
cd openwhisk-website

# Install gem dependencies
bundle install

# Start the development server default location http://127.0.0.1:4000
bin/develop

To make sure nothing is broken on the website we use html-proofer,
it checks to see if any of the links 404s, if the HTML is valid, images have alt tags and more.

Run the following command to run html-proofer:

sh
bin/test

How to Build Jekyll to Output Static Files

If you need to generate static files, run the following:

sh
# NOTE: Make sure you have already cloned the repository and moved into the directory.

# Build the site.
bundle exec jekyll build

This will build static files to a directory called _site/ in the project root. This can be used for manual deployment to a static server or with build tools like Jenkins.

Updating CSS files

Some browsers will continue to use cached copies of ".css" files even though the styles/content in the files has changed significantly. If you make any changes that affect layout, you SHOULD increment the (artificial) version number on the query parameter on the <link> within default.html which will cause (force) some clients to pull down a new main.css file (and all the cascading CSS imports as well):

html
<link rel="stylesheet" href="{{ site.github.url }}/css/main-v1.css?v=1.12">

for example, update "?v1.12" to "?v1.13".

html
<link rel="stylesheet" href="{{ site.github.url }}/css/main-v1.css?v=1.13">

Using `rbenv`

If you need to maintain your existing system Ruby version, you can use the https://github.com/rbenv/rbenv utility to dynamically switch to the version this project requires.

The project already has a .ruby_version file which indicates it requires Ruby 2.7.2. All you need do is assure once rbenv is installed that you issue the following commands (one time) from the bash shell you wish to compile the project:

sh
$ rbenv init
$ rbenv install 2.7.2
$ rbenv global 2.7.2
$ eval "$(rbenv init -)"

When opening subsequent bash terminals, you need only issue the following command (as rbenv init has updated your system .bash_profile):

sh
eval "$(rbenv init -)"

You can verify the version changed by using:

sh
$ rbenv global
$ ruby -v

Troubleshooting

If you get an error 'bundle: command not found' attempting to build the site, you may need to manually install the 'bundler' package:

sh
gem install bundler

Jenkins build

The OpenWhisk.org website is automatically built and published to Apache at:
https://openwhisk.apache.org/

Current Jenkins build status can be checked here:
https://builds.apache.org/job/OpenWhisk-website/

Issues

Report website bugs, ask questions and request features here on GitHub.

You can also join our slack domain and chat with developers. Please visit here to sign up:
https://openwhisk.apache.org/slack.html

License

Licensed under the Apache License, Version 2.0 (the "License").

Unless required by applicable law or agreed to in writing, software distributed under the license is distributed on an "as is" basis, without warranties or conditions of any kind, either express or implied. See the license for the specific language governing permissions and limitations under the license.