├── .gitignore ├── 101-workshop-nodejs ├── CONCLUSION.md ├── EXAM.md ├── GENERAL.md ├── OBJECTIVES.md ├── PREREQS.md ├── README.md ├── SYLLABUS.md ├── TROUBLESHOOTING.md ├── bonus-exercises │ ├── README.md │ ├── building-a-weather-bot │ │ └── images │ │ │ ├── incoming.png │ │ │ ├── london.png │ │ │ ├── outgoing.png │ │ │ ├── test_bot.png │ │ │ └── weather_bot.png │ ├── ex1-invoking-an-async-api.md │ └── using-the-serverless-framework │ │ └── images │ │ └── framework.png ├── ex0-what-is-serverless │ ├── README.md │ ├── REVIEW.md │ ├── images │ │ ├── 101-ex0-OW-Programming-Model-1-Web-Action.png │ │ ├── 101-ex0-OW-Programming-Model-2-Action.png │ │ ├── 101-ex0-OW-Programming-Model-2-All.png │ │ ├── 101-ex0-OW-Programming-Model-2-Feed.png │ │ ├── 101-ex0-OW-Programming-Model-2-Trigger-Rule.png │ │ ├── 101-ex0-ibm-cloud-functions-hld.png │ │ ├── 101-ex0-package-for-caas.png │ │ ├── 101-ex0-package-for-faas.png │ │ ├── 101-ex0-review-question-request-graph-1.png │ │ ├── 101-ex0-review-question-request-graph-2.png │ │ ├── 101-ex0-serverless-1-trigger-2-action.png │ │ ├── 101-ex0-serverless-2-trigger-1-action.png │ │ ├── 101-ex0-serverless-developer-joy.png │ │ ├── 101-ex0-serverless-devops-blues.png │ │ ├── 101-ex0-serverless-icf-compositions.png │ │ ├── 101-ex0-serverless-lcd-model.png │ │ ├── 101-ex0-serverless-trigger-rule-action.png │ │ ├── 101-ex0-serverless-workloads.png │ │ ├── 101-ex0-use-case-apis.png │ │ ├── 101-ex0-use-case-divide-conquer.png │ │ ├── 101-ex0-use-case-etl-pipeline.png │ │ ├── 101-ex0-use-case-periodic.png │ │ ├── tensorflow-logo-2d-trans-small.png │ │ └── tensorflow-logo-2d-trans.png │ ├── serverless-characteristics.md │ ├── serverless-defined.md │ ├── serverless-deployment-models.md │ ├── serverless-programming-model.md │ ├── serverless-use-cases.md │ └── serverless-writing-apps.md ├── ex1-creating-and-invoking-actions │ ├── README.md │ ├── REVIEW.md │ ├── action-proxy.md │ ├── async.md │ ├── create-invoke.md │ ├── ex1.2-using-action-sequences │ │ ├── README.md │ │ └── sequences.md │ ├── retrieve-logs.md │ └── use-parameters.md ├── ex2-managing-actions-with-packages │ ├── README.md │ ├── REVIEW.md │ ├── custom.md │ └── existing.md ├── ex3-connecting-actions-to-event-sources │ ├── README.md │ ├── REVIEW.md │ ├── concepts.md │ ├── feeds.md │ ├── rules.md │ └── triggers.md ├── ex4-exposing-apis-from-actions │ ├── README.md │ ├── REVIEW.md │ ├── api.md │ ├── concepts.md │ ├── images │ │ └── atom.svg │ ├── other_apis.md │ └── web-actions.md ├── ex5-ibm-cloud-functions-web-ui │ ├── README.md │ ├── REVIEW.md │ ├── actions.md │ ├── images │ │ ├── 101-ex5-action-breadcrumb.png │ │ ├── 101-ex5-action-change-params.png │ │ ├── 101-ex5-action-change-params.psd │ │ ├── 101-ex5-action-create-new-editor.png │ │ ├── 101-ex5-action-create-new.png │ │ ├── 101-ex5-action-create-new.psd │ │ ├── 101-ex5-action-create.png │ │ ├── 101-ex5-action-details.png │ │ ├── 101-ex5-action-details.psd │ │ ├── 101-ex5-action-invoke-with-name-param.png │ │ ├── 101-ex5-action-invoke-with-name-param.psd │ │ ├── 101-ex5-action-invoke-with-params.png │ │ ├── 101-ex5-action-invoke.png │ │ ├── 101-ex5-action-invoke.psd │ │ ├── 101-ex5-action-list-select.png │ │ ├── 101-ex5-action-list.png │ │ ├── 101-ex5-action-list.psd │ │ ├── 101-ex5-api-breadcrumb.png │ │ ├── 101-ex5-api-create-basic.png │ │ ├── 101-ex5-api-create-final.png │ │ ├── 101-ex5-api-create-final.psd │ │ ├── 101-ex5-api-create-operation-modal.png │ │ ├── 101-ex5-api-create-operation-modal.psd │ │ ├── 101-ex5-api-create-operation.png │ │ ├── 101-ex5-api-create.psd │ │ ├── 101-ex5-api-details.png │ │ ├── 101-ex5-api-details.psd │ │ ├── 101-ex5-api-greeting-explore-operation-tryit-result.png │ │ ├── 101-ex5-api-greeting-explore-operation-tryit.png │ │ ├── 101-ex5-api-greeting-explore-operation-tryit.psd │ │ ├── 101-ex5-api-greeting-explore-operation.png │ │ ├── 101-ex5-api-greeting-explore-operation.psd │ │ ├── 101-ex5-api-greeting-explore.png │ │ ├── 101-ex5-api-greeting-explore.psd │ │ ├── 101-ex5-api-list-create.png │ │ ├── 101-ex5-api-list.png │ │ ├── 101-ex5-api-list.psd │ │ ├── 101-ex5-entity-create-action.png │ │ ├── 101-ex5-entity-create-trigger.png │ │ ├── 101-ex5-entity-create.psd │ │ ├── 101-ex5-ibmcloud-dashboard-top-menu.png │ │ ├── 101-ex5-ibmcloud-service-dropdown.png │ │ ├── 101-ex5-monitoring.png │ │ ├── 101-ex5-trigger-breadcrumb.png │ │ ├── 101-ex5-trigger-connect-action-add-select.png │ │ ├── 101-ex5-trigger-connect-action-add-select.psd │ │ ├── 101-ex5-trigger-connect-action-add.png │ │ ├── 101-ex5-trigger-connect-action-add.psd │ │ ├── 101-ex5-trigger-connect-action-complete.png │ │ ├── 101-ex5-trigger-connect-action-existing-add.png │ │ ├── 101-ex5-trigger-connect-action-existing-add.psd │ │ ├── 101-ex5-trigger-create-configure-create.png │ │ ├── 101-ex5-trigger-create-configure-name.png │ │ ├── 101-ex5-trigger-create-configure.psd │ │ ├── 101-ex5-trigger-create-type.png │ │ ├── 101-ex5-trigger-create-type.psd │ │ ├── 101-ex5-trigger-create.png │ │ ├── 101-ex5-trigger-details.png │ │ ├── 101-ex5-trigger-details.psd │ │ ├── 101-ex5-trigger-list-select.png │ │ ├── 101-ex5-trigger-list-select.psd │ │ ├── 101-ex5-trigger-list.png │ │ └── 101-ex5-trigger-list.psd │ ├── monitoring_and_apis.md │ └── triggers.md └── source │ └── action │ ├── javascript │ ├── asyncAction.js │ ├── atom.js │ ├── empty.js │ ├── funcs.js │ ├── hello-html.js │ ├── hello-person.js │ ├── hello.js │ ├── html.js │ ├── identity.js │ ├── manual.js │ ├── proxy.js │ └── redirect.js │ └── parameters.json ├── 201-intermediate-courselets-nodejs ├── 201-using-event-providers │ ├── README.md │ ├── alarms │ │ ├── README.md │ │ └── images │ │ │ └── cloud-functions-alarm-trigger.png │ ├── cloudant │ │ ├── README.md │ │ └── images │ │ │ ├── cloudant-dashboard-link.png │ │ │ ├── create-database.png │ │ │ ├── new-document.png │ │ │ ├── new-input.png │ │ │ ├── new-service-credentials-button.png │ │ │ ├── output.png │ │ │ ├── service-credentials-menu.png │ │ │ └── view-service-credentials.png │ ├── cos │ │ ├── README.md │ │ └── images │ │ │ ├── authorizations.png │ │ │ ├── create-authorizations.png │ │ │ ├── create-bucket.png │ │ │ ├── create-button.png │ │ │ ├── custom-bucket.png │ │ │ ├── grant-authorization.png │ │ │ ├── new-bucket.png │ │ │ ├── new-cos-instance.png │ │ │ └── upload-bucket.png │ └── github │ │ ├── README.md │ │ └── images │ │ ├── github-access-scope-repo-hook.png │ │ ├── github-access-scope-repo.png │ │ ├── github-commit-new-file.png │ │ ├── github-create-a-repo.png │ │ ├── github-create-new-markdown-file.png │ │ ├── github-repo-created-with-readme.png │ │ ├── github-repo-edit-readme.png │ │ └── github-repo-save readme.png └── README.md ├── LICENSE ├── README.md ├── SUMMARY.md ├── content ├── OW-Programming-Model-1.png ├── OW-Programming-Model-2-Action.png ├── OW-Programming-Model-2-All.png ├── OW-Programming-Model-2-Feed.png ├── OW-Programming-Model-2-Trigger-Rule.png ├── OW-Programming-Model-2.png └── OW-Programming-Model-2.psd ├── iam ├── iam_create.md └── images │ ├── create_namespace.png │ └── create_namespace_modal.png ├── ibm-cloud-functions-logo-transparent.png ├── md2html.js ├── md2html.sh ├── package-lock.json ├── package.json ├── prereqs ├── README.md ├── cli-setup.md ├── cloud-functions.md ├── images │ ├── prereq-ibm-cloud-cloud-foundry-orgs-1.png │ ├── prereq-ibm-cloud-cloud-foundry-orgs-2.png │ ├── prereq-ibm-cloud-registration-1.png │ ├── prereq-ibm-cloud-registration-2.png │ ├── prereq-ibm-cloud-registration-3.png │ ├── prereq-ibm-cloud-registration-4.png │ └── prereq-ibm-cloud-registration-email.png └── signup.md ├── presentations ├── 101-review-questions-graphics.pptx ├── 2020-03-09-Serverless-CC-AI-materials.pptx └── OW-Programming-Model.pptx ├── serverless-acclaim-badge.png ├── serverless-acclaim-badge.psd ├── serverless-banner-abstract.png ├── serverless-banner-abstract.psd ├── svg ├── info-i-outline-blue.plain.svg ├── info-i-outline-blue.svg ├── success-checkmark-outline.green.plain.svg ├── success-checkmark-outline.green.svg ├── tip-outline-cyan.plain.svg ├── tip-outline-cyan.svg ├── warning-exclaim-outline-yellow.plain.svg └── warning-exclaim-outline-yellow.svg └── test.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Mac 4 | .DS_Store 5 | 6 | # NodeJS 7 | node_modules 8 | 9 | # VSCode 10 | .vscode/ 11 | settings.json 12 | 13 | # GitBook 14 | assets/ 15 | 16 | # MD to HTML tooling 17 | .html 18 | 19 | # PowerPoint temporary 20 | ~$*.ppt* 21 | -------------------------------------------------------------------------------- /101-workshop-nodejs/CONCLUSION.md: -------------------------------------------------------------------------------- 1 | 2 | {% hint style="success" %} 3 | Congratulations! You’ve successfully completed the Serverless Fundamentals using IBM Cloud Functions (ICF) course. 4 | {% endhint %} 5 | 6 | # Course summary 7 | 8 | During this course you learned: 9 | 10 | * What serverless computing is, how it works, and its basic programming model. You even learned more about serverless top use cases and patterns. 11 | 12 | * How to create, invoke, monitor, and manage serverless actions using the ICF CLI. 13 | 14 | * How to call actions from other actions and compose sequences. 15 | 16 | * How to connect your actions to built-in event sources using triggers and rules. 17 | 18 | * How to expose your actions to the web for direct access from HTTP clients and web browsers with various content types. 19 | 20 | * Navigate the web user interface to perform these features and more. 21 | 22 | ## Learn more 23 | 24 | This course has provided the fundamentals needed to understand and begin utilizing the power of serverless using ICF. 25 | 26 | If you'd like to continue to build on your knowledge, [IBM Developer](https://developer.ibm.com) provides articles, tutorials, code patterns, and more that demonstrate how to create advanced [serverless](https://developer.ibm.com/technologies/serverless/) applications that integrate with various IBM Cloud and external services. 27 | 28 | Don't forget to subscribe to the [IBM Cloud newsletter](https://developer.ibm.com/newsletters/cloud/) to stay up to date with the latest serverless content! 29 | 30 | --- 31 | 32 | {% hint style="warning" %} 33 | Don't forget to take and pass the final exam in order to receive certification! 34 | {% endhint %} 35 | -------------------------------------------------------------------------------- /101-workshop-nodejs/EXAM.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Final Exam 21 | 22 | ## What is serverless? 23 | 24 | 1. ICF scales your actions automatically only in response to event triggers. 25 | 26 | (!) True 27 | (x) False 28 | 29 | [explanation] 30 | False. ICF also scales your actions automatically in response to web or HTTP API invocations if you have enabled them as web actions and/or created a private or public API for them. 31 | [explanation] 32 | 33 | 1. You are given the following graph of usage for an application you are developing. Which of the following is a correct conclusion of the graph? 34 | 35 | ![Application Usage Graph](ex0-what-is-serverless/images/101-ex0-review-question-request-graph-2.png) 36 | 37 | (!) The usage is mostly constant, so serverless computing would be a good fit for this usage case. 38 | ( ) The usage is mostly sporadic, so serverless computing is a good fit for this usage case. 39 | (x) The usage is mostly constant, so serverless computing would be a bad fit for this usage case. 40 | ( ) The usage is mostly sporadic, so serverless computing is a bad fit for this usage case. 41 | 42 | [explanation] 43 | The usage graphs shows that requests to the application are very fairly constant, with the request rate averaging roughly 6,000 over the provided time interval. In this usage case, it is likely more cost effective to pay for dedicated servers (computing services) with enough planned capacity to handle such a load. 44 | [explanation] 45 | 46 | 1. Tobias is trying to create an image recognition model for object analysis using large amounts of raw image data. Is serverless a good choice in helping with these tasks? 47 | 48 | (!) Serverless is a great choice here, but Tobias will have to configure his account to handle the amount of processing needed. 49 | ( ) Serverless won’t work well here because processing the large amount of raw data would be too costly. 50 | ( ) Serverless is not a good choice because Tobias would need dedicated servers that have the processing power for analytics. 51 | (X) Serverless may be a good choice in both dividing the data into manageable pieces as well as analyzing the data in parallel. 52 | 53 | [explanation] 54 | This is an example of an embarassingly parallel task where serverless could be used to help in two ways. First, it can be used to divide the large data sets into smaller ones that enables parallel processing. Then it can be used again in parallel to analyze the data and aggregate the results. 55 | [explanation] 56 | 57 | ## Create and invoke actions 58 | 59 | 1. Actions cannot directly invoke other actions without using a sequence. 60 | 61 | (!) True 62 | (x) False 63 | 64 | [explanation] 65 | False. Actions can invoke other actions, acting as a proxy, using the NPM Apache OpenWhisk JavaScript library. 66 |

var openwhisk = require('openwhisk');

67 | [explanation] 68 | 69 | 1. You are able to pass parameters when invoking an action using the command line directly or indirectly using a parameter file. 70 | 71 | (x) True 72 | (!) False 73 | 74 | [explanation] 75 | True. Parameters can be passed directly when invoking an action using the --param flag or indirectly from a file using the --param-file flag. 76 | [explanation] 77 | 78 | ### Manage actions with packages 79 | 80 | 1. If you have many packages of actions, you can better organize them by creating a package that contains several similar packages. 81 | 82 | (!) True 83 | (x) False 84 | 85 | [explanation] 86 | False. Package nesting is not allowed. Remember, packages cannot contain other packages. 87 | [explanation] 88 | 89 | ### Connect actions to event sources 90 | 91 | 1. Multiple triggers can be configured to fire the same action. 92 | 93 | (!) Incorrect 94 | (x) Correct 95 | 96 | [explanation] 97 | Correct. Multiple triggers can be connected to the same action using separate rules. This allows similar event data, coming from different event sources, to be processed by the same serverless action. 98 | [explanation] 99 | 100 | ### Expose APIs from actions 101 | 102 | 1. It may be possible to construct a website entirely using serverless actions. 103 | 104 | (x) True 105 | (!) False 106 | 107 | [explanation] 108 | True. Using web actions to prepare content and make it web accessible, with any HTTP `content-type` and using dynamic data from multiple sources, makes it possible create compelling websites using only serverless. 109 | [explanation] 110 | 111 | ### Use the Web UI 112 | 113 | 1. If you wish to monitor your action invocations, you need to use the Web UI. 114 | 115 | (!) True 116 | (x) False 117 | 118 | [explanation] 119 | False. The CLI's `action poll` command allows you to see activation records as they are created (live), but you will not get the views and filters the Web UI experience provides. 120 | [explanation] 121 | -------------------------------------------------------------------------------- /101-workshop-nodejs/GENERAL.md: -------------------------------------------------------------------------------- 1 | ## Recommended skills prior to taking this course 2 | 3 | 1. Have a basic understanding of [Node.js](https://nodejs.org/) ([JavaScript](https://nodejs.org/about/)) programming. 4 | 5 | ## Troubleshooting lab exercises 6 | 7 | If you encounter an unexpected error when executing the steps of the exercises, please use this link to find tips on troubleshooting the reported error: 8 | 9 | - [Troubleshooting guide](TROUBLESHOOTING.md) 10 | -------------------------------------------------------------------------------- /101-workshop-nodejs/OBJECTIVES.md: -------------------------------------------------------------------------------- 1 | _After you complete this course, you will be able to:_ 2 | 3 | - Comprehend how serverless computing works and ways it can be used in cloud applications 4 | 5 | - Distinguish use cases and patterns compatible with Serverless 6 | 7 | - Create and manage serverless functions using the IBM Cloud Functions platform 8 | 9 | - Use packages to organize your functions and create reusable building blocks 10 | 11 | - Automate your functions using alarm events 12 | 13 | - Expose functions as to the web accessible endpoints and as APIs that return different content types 14 | 15 | - Navigate the web user interface to perform similar tasks that mirror CLI commands 16 | -------------------------------------------------------------------------------- /101-workshop-nodejs/PREREQS.md: -------------------------------------------------------------------------------- 1 | # Install lab prerequisites 2 | 3 | In order to put into practice the serverless concepts and patterns already discussed, we will use IBM Cloud and the [IBM Cloud Functions](https://cloud.ibm.com/functions), service from this point on for all lab exercises. This will require a free account on IBM Cloud to utilize the IBM Cloud Functions (ICF) service. 4 | 5 | To perform course labs, you will need to follow these steps: 6 | 7 | ## Register for and configure a free IBM Cloud Account 8 | 9 | 1. Register for a free IBM Cloud account using the linked instructions: 10 | - [https://cloud.ibm.com/registration](https://cloud.ibm.com/registration) 11 | 12 | 2. Target a region that supports IBM Cloud Functions using the following link: 13 | - [Target a supported regions](https://cloud.ibm.com/docs/openwhisk?topic=cloud-functions-cloudfunctions_regions) using the CLI. 14 | 15 | ## Install the IBM Cloud Command Line Interface (CLI) and Cloud Functions plugin 16 | 17 | 1. Install the [IBM Cloud Command Line Interface (CLI)](https://cloud.ibm.com/docs/cli?topic=cloud-cli-getting-started) by following the steps outlined on the linked page. 18 | 19 | 2. Install the [Cloud Functions (CF)](https://cloud.ibm.com/functions/learn/cli) plugin by following the steps outlined on the linked page. 20 | 21 | {% hint style="info" %} 22 | An independent [step-by-step guide](https://github.com/IBM/cloud-functions-workshops/tree/master/prereqs) (with screenshots) is available that covers both the IBM Cloud CLI and Cloud Functions plugin installations together. 23 | {% endhint %} 24 | 25 | {% hint style="success" %} 26 | Now we are ready to run all the lab exercises! 27 | {% endhint %} 28 | -------------------------------------------------------------------------------- /101-workshop-nodejs/README.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Welcome to the Serverless Computing using Cloud Functions - Developer I course 21 | 22 | Hello, future serverless developers! 23 | 24 | Welcome to a course that is designed to teach you serverless computing essentials! Here you will learn how to develop serverless applications composed of loosely coupled microservice-like functions. Although many cloud providers offer different implementations of serverless using cloud functions, this course specifically guides you through several labs that demonstrate how to implement essential concepts using [IBM Cloud Functions](https://cloud.ibm.com/functions) (ICF). ICF is a Functions-as-a-Service (FaaS) platform based on [Apache OpenWhisk](https://openwhisk.apache.org/). 25 | 26 | This course will also walk you through the following: 27 | 28 | * An overview of serverless and its programming and deployment models 29 | * Top use cases 30 | * How to set up a development environment 31 | * A series of hands-on labs that demonstrate how easy it is to create, deploy, and invoke serverless functions 32 | 33 | Once you are comfortable with managing serverless functions, you will learn how to: 34 | 35 | * Automate your functions to fire automatically by connecting them to event sources 36 | * Expose your functions as public, web-accessible HTTP endpoints and APIs 37 | 38 | Without further ado, welcome to the future of cloud development; you'll never want to manage another server again! 39 | 40 | Are you ready? Let's go! 41 | 42 | {% hint style="info" %} 43 | Although this course uses the [Node.js](https://nodejs.org/) ([JavaScript](https://nodejs.org/about/)) language in its labs, you are free to use your favorite supported language, such as Python, PHP or Swift by simply supplying your own equivalent functional code. 44 | {% endhint %} 45 | -------------------------------------------------------------------------------- /101-workshop-nodejs/SYLLABUS.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | ## Syllabus 21 | 22 | ### Module 1 - Serverless essentials 23 | 24 | - How serverless is simplifying the Ops landscape for developers 25 | - Understand the basic serverless programming model and semantics of IBM Cloud Functions 26 | - Differentiate a Function-as-a-Service (FaaS) from a Container-as-a-Service (CaaS) 27 | - Top use cases for serverless 28 | - How IBM Cloud Functions implements serverless 29 | 30 | ### Module 2 - Create and invoke actions (lab) 31 | 32 | - Install lab prerequisites 33 | - Create and invoke actions 34 | - Use action parameters 35 | - Retrieve action logs 36 | - Asynchronous actions 37 | - Practice action sequences 38 | 39 | ### Module 3 - Manage actions with packages (lab) 40 | 41 | - Use packaged actions 42 | - Create your own packages 43 | 44 | ### Module 4 - Connect actions to event sources (lab) 45 | 46 | - Understand the concepts 47 | - Create triggers 48 | - Practice rules 49 | - Connect trigger feeds 50 | 51 | ### Module 5 - Expose APIs from actions (lab) 52 | 53 | - Understand the concepts 54 | - Create web-enabled actions 55 | - API management of web actions 56 | 57 | ### Module 6 - Use the Web User Interface (Web UI) 58 | 59 | - create and invoke an action 60 | - create triggers with implicit rules 61 | - expose web actions 62 | - create an API 63 | - explore the monitoring dashboard 64 | -------------------------------------------------------------------------------- /101-workshop-nodejs/TROUBLESHOOTING.md: -------------------------------------------------------------------------------- 1 | 2 | # Troubleshooting lab exercises 3 | 4 | {% hint style="tip" %} 5 | You may skip this section and continue onto the course. Feel free to reference this if you have any trouble during lab exercises. 6 | {% endhint %} 7 | 8 | ## Organization 9 | 10 | This guide is organized to describe error conditions by IBM Cloud Functions (ICF) entity type, such as actions, triggers and APIs, and the CLI commands the exhibit the error. 11 | 12 | ## Contact us 13 | 14 | Please contact the course staff to report any errors that are not covered and be sure to include: 15 | 16 | * IBM Cloud Namespace and region 17 | * IBM CLI commands that exhibit the error and 18 | * Results of "get" commands on any affected actions, triggers or APIs. For example: 19 | 20 | ```bash 21 | ibmcloud fn [ action | trigger | api ] get 22 | ``` 23 | 24 | ## Action invoke errors 25 | 26 | Errors reported as a result of an `ibmcloud action invoke` command. 27 | 28 | ### Reserved properties error 29 | 30 | You may see the following error while attempting to invoke the an action with parameters: 31 | 32 | ```text 33 | error: Unable to invoke action 'hello': Request defines parameters that are not allowed (e.g., reserved properties). 34 | ``` 35 | 36 | This likely means the action was turned into a web action, causing all its bound parameters to become `final` (protected). 37 | 38 | You can verify this by looking at the value of the `final` annotation of the action using the `get` command. For example, the `hello` action has its `final` annotation set to `true` which would cause this error: 39 | 40 | ```bash 41 | ibmcloud fn action get hello 42 | 43 | ok: got action hello 44 | { 45 | "name": "hello", 46 | ... 47 | "annotations": [ 48 | ... 49 | { 50 | "key": "final", 51 | "value": true 52 | } 53 | ], 54 | ... 55 | } 56 | ``` 57 | 58 | The simplest solution is to set the `final` annotation to `false`. This example shows how to do this with the `hello` action: 59 | 60 | ```bash 61 | ibmcloud fn action update hello -a final false 62 | ok: updated action hello 63 | ``` 64 | -------------------------------------------------------------------------------- /101-workshop-nodejs/bonus-exercises/README.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Bonus Exercises 21 | 22 | * [Calling an external API from an Async action](ex1-invoking-an-async-api.md) 23 | -------------------------------------------------------------------------------- /101-workshop-nodejs/bonus-exercises/building-a-weather-bot/images/incoming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/bonus-exercises/building-a-weather-bot/images/incoming.png -------------------------------------------------------------------------------- /101-workshop-nodejs/bonus-exercises/building-a-weather-bot/images/london.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/bonus-exercises/building-a-weather-bot/images/london.png -------------------------------------------------------------------------------- /101-workshop-nodejs/bonus-exercises/building-a-weather-bot/images/outgoing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/bonus-exercises/building-a-weather-bot/images/outgoing.png -------------------------------------------------------------------------------- /101-workshop-nodejs/bonus-exercises/building-a-weather-bot/images/test_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/bonus-exercises/building-a-weather-bot/images/test_bot.png -------------------------------------------------------------------------------- /101-workshop-nodejs/bonus-exercises/building-a-weather-bot/images/weather_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/bonus-exercises/building-a-weather-bot/images/weather_bot.png -------------------------------------------------------------------------------- /101-workshop-nodejs/bonus-exercises/ex1-invoking-an-async-api.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Call an external API from an async action 21 | 22 | This exercise challenges you to create a new action that takes a price and currency and returns a message that contains the equivalent amount of Bitcoin. The actual conversion will be done by calling an external API asynchronously from your function. 23 | 24 | ## Input 25 | 26 | The action should take two parameters: `amount` and `currency`. The `amount` parameter is a number and `currency` is a three letter [currency code](https://www.iban.com/currency-codes.html). 27 | 28 | ## Output 29 | 30 | Return the following JSON template with the input parameters and bitcoin amounts: 31 | 32 | ```json 33 | { 34 | "amount": 1.5, 35 | "message": "10000 USD is worth 1.5 bitcoins." 36 | } 37 | ``` 38 | 39 | If either the `amount` or `currency` parameters are missing, return an error with details. 40 | 41 | ## Resources 42 | 43 | This [Coindesk Version 1 API](https://api.coindesk.com/v1/bpi/currentprice.json) returns real time Bitcoin prices. This includes rates for the `USD`, `GBP`, and `EUR` currencies. 44 | 45 | This [Currency Converter API](https://free.currencyconverterapi.com/) returns exchange rates between traditional currencies. 46 | 47 | Use the `request-promise` [module](https://www.npmjs.com/package/request-promise) to make external API requests. It comes pre-installed in the runtime. 48 | 49 | ## Tests 50 | 51 | ### Test with currencies in the Coindesk API response 52 | 53 | ```bash 54 | ibmcloud fn action invoke bitcoin -r -p amount 1000 -p currency USD 55 | ``` 56 | 57 | ```json 58 | { 59 | "amount": "0.160814", 60 | "label": "1000 USD is worth 0.160814 bitcoins." 61 | } 62 | ``` 63 | 64 | ```bash 65 | ibmcloud fn action invoke bitcoin -r -p amount 1000 -p currency EUR 66 | ``` 67 | 68 | ```json 69 | { 70 | "amount": "0.187235", 71 | "label": "1000 EUR is worth 0.187235 bitcoins." 72 | } 73 | ``` 74 | 75 | ```bash 76 | ibmcloud fn action invoke bitcoin -r -p amount 1000 -p currency GBP 77 | ``` 78 | 79 | ```json 80 | { 81 | "amount": "0.213012", 82 | "label": "1000 GBP is worth 0.213012 bitcoins." 83 | } 84 | ``` 85 | 86 | ### Test with currencies not in the Coindesk API response. 87 | 88 | ```bash 89 | ibmcloud fn action invoke bitcoin -r -p amount 1000 -p currency AUD 90 | ``` 91 | 92 | ```json 93 | { 94 | "amount": "0.10814", 95 | "label": "1000 AUD is worth 0.10814 bitcoins." 96 | } 97 | ``` 98 | 99 | ### Test with missing parameters 100 | 101 | ```bash 102 | ibmcloud fn action invoke bitcoin -r -p amount 1000 103 | ``` 104 | 105 | ```json 106 | { 107 | "error": "Missing mandatory argument: currency" 108 | } 109 | ``` 110 | 111 | ```bash 112 | ibmcloud fn action invoke bitcoin -r -p currency GBP 113 | ``` 114 | 115 | ```json 116 | { 117 | "error": "Missing mandatory argument: amount" 118 | } 119 | ``` 120 | -------------------------------------------------------------------------------- /101-workshop-nodejs/bonus-exercises/using-the-serverless-framework/images/framework.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/bonus-exercises/using-the-serverless-framework/images/framework.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/README.md: -------------------------------------------------------------------------------- 1 | 19 | ## Learning objectives 20 | 21 | In this lesson, you will learn: 22 | 23 | * What serverless computing is and its characteristics 24 | * How serverless simplifies the operations landscape for developers 25 | * The components of a serverless programming model based upon the Observer pattern 26 | * The differences between Function-as-a-Service (FaaS) and Container-as-a-Service (CaaS) workloads and deployment models 27 | * The top use cases for serverless, including: 28 | * Problems that serverless can best solve 29 | * Problems where traditional servers may work best 30 | * Why ICF is a mature serverless platform that enables developer agility by supporting: 31 | * Polyglot programming languages 32 | * Logical functional compositions 33 | * Built-in event adapters to various services and data sources 34 | 35 | In short, _"What is serverless... and what is it good for?_. 36 | 37 | --- 38 | 39 | Upon completion of this lesson, you should be able to: 40 | 41 | * Summarize serverless computing in simple terms and be able to concisely describe why, as a technology, it is an essential part of low-cost, rapid cloud application development 42 | * Identify and describe typical patterns of real-world problems that serverless computing is ideal in solving 43 | * Describe advanced features ICF supports that make it ideal for serverless application development 44 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-OW-Programming-Model-1-Web-Action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-OW-Programming-Model-1-Web-Action.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-OW-Programming-Model-2-Action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-OW-Programming-Model-2-Action.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-OW-Programming-Model-2-All.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-OW-Programming-Model-2-All.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-OW-Programming-Model-2-Feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-OW-Programming-Model-2-Feed.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-OW-Programming-Model-2-Trigger-Rule.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-OW-Programming-Model-2-Trigger-Rule.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-ibm-cloud-functions-hld.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-ibm-cloud-functions-hld.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-package-for-caas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-package-for-caas.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-package-for-faas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-package-for-faas.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-review-question-request-graph-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-review-question-request-graph-1.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-review-question-request-graph-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-review-question-request-graph-2.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-1-trigger-2-action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-1-trigger-2-action.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-2-trigger-1-action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-2-trigger-1-action.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-developer-joy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-developer-joy.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-devops-blues.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-devops-blues.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-icf-compositions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-icf-compositions.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-lcd-model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-lcd-model.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-trigger-rule-action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-trigger-rule-action.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-workloads.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-serverless-workloads.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-use-case-apis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-use-case-apis.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-use-case-divide-conquer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-use-case-divide-conquer.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-use-case-etl-pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-use-case-etl-pipeline.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-use-case-periodic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/101-ex0-use-case-periodic.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/tensorflow-logo-2d-trans-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/tensorflow-logo-2d-trans-small.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/images/tensorflow-logo-2d-trans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex0-what-is-serverless/images/tensorflow-logo-2d-trans.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/serverless-characteristics.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Characteristics of serverless 21 | 22 | ## Taking the Ops out of DevOps 23 | 24 | In today's agile-focused world, developers are now, more than ever, expected to understand the operational considerations of deploying, hosting, and maintaining their applications on the cloud. This often means developers spend less time coding applications and much more time worrying about the operational aspects. 25 | 26 | 31 | ![The DevOps blues](images/101-ex0-serverless-devops-blues.png) 32 | 33 | ## NoOps for developers 34 | 35 | To enable developers to focus on coding, providers of serverless computing strive to approach **zero** operational considerations. This can be achieved by offloading all the labor-intensive operational tasks to the serverless provider which includes: 36 | 37 | - Maximizing compute, memory, and networking utilization 38 | 39 | - Minimizing compute costs by using a _[Pay-As-You-GO (PAYGO)](https://en.wikipedia.org/wiki/PAYGO)_ cost model 40 | 41 | - Guaranteeing all the Ops, including: 42 | - Scaling 43 | - Low latency 44 | - High Availability (HA) 45 | - Multi-region 46 | - Monitoring 47 | - Logging 48 | - Security 49 | 50 | {% hint style="warning" %} 51 | Savings on your serverless operational features may vary by provider and Service License Agreements (SLAs). 52 | {% endhint %} 53 | 54 | {% hint style="info" %} 55 | IBM Cloud Functions (ICF) and its SLA offers operational services at the highest level of quality and service for every price plan. 56 | {% endhint %} 57 | 58 | ## Back to coding 59 | 60 | Thanks to serverless, once the Ops is taken out of DevOps, developers can return their attention to writing amazing applications that focus on business logic. The result is not only increased agility delivering software based on actual customer needs, but also serves to maximize developer joy in doing their daily work. 61 | 62 | 67 | ![Serverless increases developer's joy!](images/101-ex0-serverless-developer-joy.png) 68 | 69 | {% hint style="success" %} 70 | The ICF serverless platform not only delivers on all the operational features, but also exceeds what most providers offer, while always keeping the focus on the developer! 71 | {% endhint %} 72 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/serverless-defined.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # What is serverless? 21 | 22 | It's most likely that the term _serverless_ was coined to attract the attention of developers wishing to reduce the server costs of running their applications. Although the name implies that code can be run without the need for classic servers, that simply is not true! 23 | 24 | There are a number of definitions for serverless concepts, but for the purpose of this course, serverless is defined as follows: 25 | 26 | {% hint style="definition" %} 27 | **serv·er·less** 28 | /ˈsərvərləs/ 29 | _adjective_ (of computing) 30 | 1. _Event-driven application programming using stand-alone functions with no deployment or operational considerations_ 31 | {% endhint %} 32 | 33 | {% hint style="info" %} 34 | To be clear, **serverless is a misnomer**. Why? Because servers exist but are not a concern for developers! 35 | {% endhint %} 36 | 37 | Next, let's explore some of the characteristics of serverless... 38 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex0-what-is-serverless/serverless-deployment-models.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Serverless deployment models 21 | 22 | ## Functions versus containers 23 | 24 | Serverless platforms typically support the management and deployment of serverless functions either using: 25 | 26 | - **Functions directly** where the: 27 | - Provider uses an orchestration system optimized for Function-as-a-Service (FaaS). 28 | - Functions are loaded and run on pre-configured, language-specific runtimes. 29 | 30 | - **Pre-packaged containers** where the: 31 | - Provider uses Container-as-a-Service (CaaS) container-orchestration platforms like [Kubernetes](https://kubernetes.io/) and treats them as single-function applications. 32 | - Developer must package functions within containers, along with any necessary language dependencies. This requires a service framework that can handle HTTP network requests, invoke the functions, and return responses. 33 | 34 | ![Serverless workloads can be functions or functions packaged in containers](images/101-ex0-serverless-workloads.png) 35 | 36 | ## Packaging for serverless FaaS 37 | 38 | In general, with a FaaS serverless implementation, you need only to submit a single function and any dependencies (for example, packages or libraries) that are not already built into the language runtime the serverless provider prepares. This packaging step usually involves creating an archive format like ZIP or JAR (Java). 39 | 40 | In these cases, the serverless provider usually has ready-made containers that contain system and language libraries for languages such as JavaScript (Node.js), Python, Java, and perhaps other useful libraries. These other libraries may support, for example, data transformations, network access, and connections to databases and message queues. 41 | 42 | #### Typical packaging steps 43 | 44 | ![Packaging functions for a FaaS platform](images/101-ex0-package-for-faas.png) 45 | 46 | 1. Write your function in a language that the FaaS platform supports. 47 | 2. Select the target language runtime and version. _You should also find out what additional libraries the runtime may already include._ 48 | 3. If needed, create an archive with your function and any required libraries not already included in the runtime. 49 | 4. Submit the function or archive it to a FaaS platform with a selected runtime identifier. This is typically done through a supported API client. 50 | 51 | ## Packaging for serverless CaaS 52 | 53 | With a serverless platform that is designed for containers, you must select a base container and build your own microservice stack to host and run your function. This typically involves selecting a base runtime container for your language and version. Then, you select and install a service framework that can support HTTP network connections. Next, you install your function and dependent application libraries into that service framework. Finally, you export that function on an endpoint (route) that is compatible with the serverless platform. 54 | 55 | #### Additional responsibilities for CaaS functions 56 | 57 | With the CaaS approach, other operational responsibilities now become the responsibility of the developer preparing the container. You are responsible for the overall container security and maintaining the versions of not only the base container, but also of their chosen service framework. You also need to be aware of any supporting libraries. In addition, plans may have to be made to support capturing function-level logs and metrics which normally would be transparent with a FaaS approach. 58 | 59 | #### Typical packaging steps 60 | 61 | ![Packaging functions for a CaaS platform](images/101-ex0-package-for-caas.png) 62 | 63 | 1. Write your function and plan to host it using a language-specific service framework. 64 | 2. Select a base image from a repository with the language runtime version you desire. If you are able to, select one that may have your service framework already installed. 65 | 3. Build your function, any supporting libraries needed, and service framework if it’s not already included in the image. 66 | 4. Export your FaaS endpoint from your framework and configure the framework as needed to export logs and metrics. 67 | 5. Submit the resultant image to the CaaS serverless platform. This could be a direct submission or indirect from a supported image repository. 68 | 69 | {% hint style="tip" %} 70 | ICF is a FaaS which runs functions fast, but also gives you the option to "bring your own container" using a Docker SDK. This feature allows you to create Docker containers optimized for any language with only the libraries and versions you need while exploring a FaaS! 71 | {% endhint %} 72 | 73 | {% hint style="success" %} 74 | Congratulations! Now you understand the general methods serverless providers use to manage and scale functions with FaaS or CaaS! Learn more about [Preparing apps for actions](https://cloud.ibm.com/docs/openwhisk?topic=cloud-functions-prep) in ICF. 75 | {% endhint %} 76 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex1-creating-and-invoking-actions/README.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Create and invoke actions 21 | 22 | This exercise will introduce the concepts needed to create and use **actions** with IBM Cloud Functions (ICF). If you recall, the _Action_ entity was shown as part of the ICF programming model in the previous chapter. 23 | 24 | Once you have completed this exercise, you will know how to: 25 | 26 | * Create and invoke actions 27 | * Pass parameters to actions 28 | * Create actions which return asynchronous results 29 | 30 | After this, you’ll be able to create simple serverless functions using ICF! 31 | 32 | ## Background 33 | 34 | Actions are stateless code snippets (functions) that run on the ICF platform. The platform supports functions written in JavaScript (Node.js), Python, PHP, Ruby or Swift as well as many other programming languages. It also supports functions implemented as executables (binary programs) packaged in Docker containers. 35 | 36 | Actions can be used to do many things. For example, an action can be used to respond to a database change, aggregate a set of API calls, post a Tweet, or even work with AI and analytics services to detect objects in an image or streamed video. 37 | 38 | Actions can be explicitly invoked or run in response to an event. In either case, each run of an action results in an activation record that is identified by a unique activation ID. The input to an action and the result of an action are a dictionary of key-value pairs, where the key is a string and the value a valid JSON value. Actions can also be composed of calls to other actions or a defined sequence of actions. 39 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex1-creating-and-invoking-actions/REVIEW.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Review: Create and invoke actions 21 | 22 | 1. If you were to execute the following command which invokes a Hello World action: 23 | 24 |

ibmcloud fn action invoke hello

25 | 26 | it would return with an activation ID and an HTTP response generated by the function. 27 | 28 | (!) True 29 | (x) False 30 | 31 | [explanation] 32 | False. The command did not use the --blocking flag so only an activation ID would be returned. A separate command would be needed against the activation ID to retrieve the response which would be available after the function completed execution. 33 | [explanation] 34 | 35 | 2. When invoking actions, parameter values can be any valid JSON value, including nested objects. 36 | 37 | (x) True 38 | (!) False 39 | 40 | [explanation] 41 | True. You are able to pass nested JSON objects when invoking actions using the command line.

For example: 42 | ibmcloud fn action invoke add-job -p job '{"area": "marketing", "title": "director"}' 43 |

44 | [explanation] 45 | 46 | 3. It is not possible to monitor activation logs in real time using the command line. 47 | 48 | (!) True 49 | (x) False 50 | 51 | [explanation] 52 | False. You simply need to issue the poll command for activations as follows: 53 |

ibmcloud fn activation poll

54 | [explanation] 55 | 56 | 4. It is impossible to perform a blocking invocation on an asynchronous action. 57 | 58 | (!) True 59 | (x) False 60 | 61 | [explanation] 62 | False. Using `Promises` in Node.js, it is possible for your function to return while waiting for the result of the promise. 63 | [explanation] 64 | 65 | 5. If an action in the middle of a sequence fails, the platform will return the error after the last action in the sequence is invoked. 66 | 67 | (!) True 68 | (x) False 69 | 70 | [explanation] 71 | False. The platform will return the error from the failing action immediately. 72 | [explanation] 73 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex1-creating-and-invoking-actions/action-proxy.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Calling other actions 21 | 22 | Using serverless platforms to implement reusable functions means you will often want to invoke one action from another. IBM Cloud Functions (ICF) provides a [RESTful API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/openwhisk/openwhisk/master/core/controller/src/main/resources/apiv1swagger.json) to invoke actions programmatically. 23 | 24 | Rather than having to [manually construct the HTTP requests](https://github.com/apache/incubator-openwhisk/blob/master/docs/rest_api.md#actions) to invoke actions from within the ICF runtime, client libraries are pre-installed to make this easier. 25 | 26 | These libraries make it simple to invoke other actions, fire triggers, and access all other platform services. 27 | 28 | ## Example proxy 29 | 30 | Let's look at an example of creating a proxy action which invokes another action (like your `hello` action) if a password is present in the input parameters. 31 | 32 | 1. Create the new action named `proxy` from the following source files: 33 | 34 | ```javascript 35 | var openwhisk = require('openwhisk'); 36 | 37 | function main(params) { 38 | if (params.password !== 'secret') { 39 | throw new Error("Password incorrect!") 40 | } 41 | 42 | var ow = openwhisk(); 43 | return ow.actions.invoke({name: "hello", blocking: true, result: true, params: params}) 44 | } 45 | ``` 46 | 47 | ```bash 48 | ibmcloud fn action create proxy proxy.js 49 | ``` 50 | 51 | {% hint style="info" %} 52 | The function uses the [NPM Apache OpenWhisk](https://www.npmjs.com/package/openwhisk) JavaScript library which is pre-installed in the ICF runtime (so you do not need to package it). Its source code can be found here: [https://github.com/apache/openwhisk-client-js/](https://github.com/apache/openwhisk-client-js/). 53 | {% endhint %} 54 | 55 | 2. Invoke the proxy with an incorrect password: 56 | 57 | ```bash 58 | ibmcloud fn action invoke proxy -p password wrong -r 59 | ``` 60 | 61 | ```json 62 | { 63 | "error": "An error has occurred: Error: Password incorrect!" 64 | } 65 | ``` 66 | 67 | {% hint style="tip" %} 68 | On the invoke call above, you used the short form for the `--result` flag which is `-r`. 69 | {% endhint %} 70 | 71 | 3. Invoke the proxy with the correct password: 72 | 73 | ```bash 74 | ibmcloud fn action invoke proxy -p password secret -p name Bernie -p place Vermont -r 75 | ``` 76 | 77 | ```json 78 | { 79 | "greeting": "Hello Bernie from Vermont" 80 | } 81 | ``` 82 | 83 | 4. Review the activations list to show both actions were invoked: 84 | 85 | ```bash 86 | ibmcloud fn activation list -l 2 87 | ``` 88 | 89 | ```text 90 | Activation ID Kind Start Duration Status Entity 91 | 8387302c81dc4d2d87302c81dc4d2dc6 nodejs:10 cold 35ms success hello:0.0.4 92 | e0c603c242c646978603c242c6c6977f nodejs:10 cold 438ms success proxy:0.0.1 93 | ``` 94 | 95 | {% hint style="tip" %} 96 | On the invoke call above, you used the short form for the `--last` flag which is `-l` with a parameter to only `list` the last `2` activations. 97 | {% endhint %} 98 | 99 | {% hint style="success" %} 100 | Congratulations on proxying an action! Be sure to [check out all the cool things](https://github.com/apache/openwhisk-client-js/#examples) the NPM OpenWhisk JavaScript library can be used for. Everything from invoking triggers to firing events to chaining action calls within actions can be performed! 101 | {% endhint %} 102 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex1-creating-and-invoking-actions/async.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Asynchronous actions 21 | 22 | ## Return asynchronous results 23 | 24 | JavaScript functions that run asynchronously may need to return the activation result after the `main` function has returned. You can accomplish this by returning a Node.js `Promise` in your action. 25 | 26 | 1. Save the following content in a file called `asyncAction.js`: 27 | 28 | ```javascript 29 | function main(args) { 30 | return new Promise(function(resolve, reject) { 31 | setTimeout(function() { 32 | resolve({ done: true }); 33 | }, 2000); 34 | }) 35 | } 36 | ``` 37 | 38 | Notice that the `main` function returns a promise, which indicates that the activation hasn't completed yet, but is expected to in the future. 39 | 40 | The `setTimeout()` JavaScript function, in this case, waits for two seconds before calling the callback function. This represents the asynchronous code and goes inside the promise's callback function. 41 | 42 | The promise's callback takes two arguments, resolve and reject, which are both functions. The call to `resolve()`fulfills the promise and indicates that the activation has completed normally. 43 | 44 | A call to `reject()` can be used to reject the promise and signal that the activation has completed abnormally. 45 | 46 | ## Test asynchronous timeouts 47 | 48 | 1. Run the following commands to create the action and invoke it: 49 | 50 | ```bash 51 | ibmcloud fn action create asyncAction asyncAction.js 52 | ``` 53 | 54 | ```bash 55 | ibmcloud fn action invoke --result asyncAction 56 | ``` 57 | 58 | ```json 59 | { 60 | "done": true 61 | } 62 | ``` 63 | 64 | Notice that you performed a blocking invocation of an asynchronous action. 65 | 66 | 2. Fetch the last activation log to see how long the async activation took to complete: 67 | 68 | ```text 69 | ibmcloud fn activation get --last 70 | ``` 71 | 72 | ```json 73 | { 74 | ... 75 | "start": 1574133220119, 76 | "end": 1574133222155, 77 | "duration": 2036, 78 | ... 79 | } 80 | ``` 81 | 82 | Checking the `duration` field in the activation record, you can see that this activation took slightly over two seconds to complete. 83 | 84 | {% hint style="info" %} 85 | Actions have a `timeout` parameter that enforces the maximum duration for an invocation. This value defaults to 60 seconds and can be changed to a maximum of 5 minutes. 86 | {% endhint %} 87 | 88 | Let's look at what happens when an action invocation takes longer than the `timeout`. 89 | 90 | 1. Update the `asyncAction` timeout to 1000ms: 91 | 92 | ```bash 93 | ibmcloud fn action update asyncAction --timeout 1000 94 | ``` 95 | 96 | ```text 97 | ok: updated action asyncAction 98 | ``` 99 | 100 | 2. Invoke the action and block on the result: 101 | 102 | ```bash 103 | ibmcloud fn action invoke asyncAction --result 104 | ``` 105 | 106 | ```json 107 | { 108 | "error": "The action exceeded its time limits of 1000 milliseconds." 109 | } 110 | ``` 111 | 112 | The error message returned by the platform indicates the action didn't return a response within the user-specified timeout. If we change the `timeout` back to a value higher than the artificial delay in the function, it should work again. 113 | 114 | 3. Update the `asyncAction` timeout to `10000 ms`: 115 | 116 | ```bash 117 | ibmcloud fn action update asyncAction --timeout 10000 118 | ``` 119 | 120 | ```text 121 | ok: updated action asyncAction 122 | ``` 123 | 124 | 4. Invoke the action and block on the result: 125 | 126 | ```bash 127 | ibmcloud fn action invoke asyncAction --result 128 | ``` 129 | 130 | ```json 131 | { 132 | "done": true 133 | } 134 | ``` 135 | 136 | 139 | 140 | {% hint style="tip" %} 141 | Asynchronous actions are necessary for calling other APIs or cloud services. Don't forget about that timeout though! 142 | {% endhint %} 143 | 144 | {% hint style="success" %} 145 | The power of asynchronous actions is now yours! There is no need to wait for those longer-running functions, as ICF does that for you! Next, let's look at how we might compose simple chains of actions using sequences. 146 | {% endhint %} 147 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex1-creating-and-invoking-actions/ex1.2-using-action-sequences/README.md: -------------------------------------------------------------------------------- 1 | # Use action sequences 2 | 3 | This exercise will explain how to use sequences to compose new meta-actions from existing actions on IBM Cloud Functions (ICF). 4 | 5 | Once you have completed this exercise, you will: 6 | 7 | * Understand what action sequences do and how they work. 8 | * Know how to create, deploy, and invoke a sample action sequence. 9 | * Have used deliberate errors to stop processing the action sequence. 10 | 11 | More importantly, you will be able to use action sequences on ICF! 12 | 13 | ## Background 14 | 15 | Developers often want to build actions as reusable components which can be combined to build higher-order serverless functions. 16 | 17 | For example, what if you have serverless functions to implement an external API and want to enforce HTTP authentication? Rather than manually replicating the same authentication code across all action handlers, you can build an authentication action which can be invoked programmatically at runtime. 18 | 19 | Unfortunately, this approach does incur additional charges. The application will be charged twice when the authentication function is called, as the calling action has to sit idle waiting for the response from the authentication function. 20 | 21 | {% hint style="success" %} 22 | Fortunately, ICF has a special type of action, called action sequences, that resolve this problem! 23 | {% endhint %} 24 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex1-creating-and-invoking-actions/retrieve-logs.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Retrieve action logs 21 | 22 | Application logs are essential to debugging production issues. In IBM Cloud Functions (ICF), all output written to `stdout` and `stderr` by actions is available in the activation records. 23 | 24 | ## Create activation logs 25 | 26 | 1. Create a new action named `logs` from the following source files: 27 | 28 | ```javascript 29 | function main(params) { 30 | console.log("function called with params", params) 31 | console.error("this is an error message") 32 | return { result: true } 33 | } 34 | ``` 35 | 36 | ```bash 37 | ibmcloud fn action create logs logs.js 38 | ``` 39 | 40 | ```bash 41 | ok: created action logs 42 | ``` 43 | 44 | 2. Invoke the `logs` action to generate logs: 45 | 46 | ```bash 47 | ibmcloud fn action invoke -r logs -p hello world 48 | ``` 49 | 50 | ```json 51 | { 52 | "result": true 53 | } 54 | ``` 55 | 56 | ## Access activation logs 57 | 58 | Retrieve the activation record to verify logs have been recorded: 59 | 60 | ```text 61 | ibmcloud fn activation get --last 62 | ``` 63 | 64 | ```json 65 | ok: got activation 9fc044881705479580448817053795bd 66 | { 67 | ... 68 | "logs": [ 69 | "20xx-11-14T09:49:03.021Z stdout: function called with params { hello: 'world' }", 70 | "20xx-11-14T09:49:03.021Z stderr: this is an error message" 71 | ], 72 | ... 73 | } 74 | ``` 75 | 76 | Logs can also be retrieved without showing the whole activation record, using the `activation logs` command: 77 | 78 | ```bash 79 | ibmcloud fn activation logs --last 80 | ``` 81 | 82 | ```text 83 | 20xx-11-14T09:49:03.021404683Z stdout: function called with params { hello: 'world' } 84 | 20xx-11-14T09:49:03.021816473Z stderr: this is an error message 85 | ``` 86 | 87 | ## Poll activation logs 88 | 89 | Activation logs can be monitored in real time, rather than manually retrieving individual activation records. 90 | 91 | 1. In another terminal, run the following command to monitor logs from the `logs` actions: 92 | 93 | ```bash 94 | ibmcloud fn activation poll 95 | ``` 96 | 97 | ```text 98 | Enter Ctrl-c to exit. 99 | Polling for activation logs 100 | ``` 101 | 102 | 2. In your original terminal, run the following command multiple times: 103 | 104 | ```bash 105 | ibmcloud fn action invoke logs -p hello world 106 | ``` 107 | 108 | ```text 109 | ok: invoked /_/logs with id 0e8d715393504f628d715393503f6227 110 | ``` 111 | 112 | 3. Check the output from the `poll` command to see the activation logs: 113 | 114 | ```bash 115 | Activation: 'logs' (ae57d06630554ccb97d06630555ccb8b) 116 | [ 117 | "20xx-11-14T09:56:17.8322445Z stdout: function called with params { hello: 'world' }", 118 | "20xx-11-14T09:56:17.8324766Z stderr: this is an error message" 119 | ] 120 | 121 | Activation: 'logs' (0e8d715393504f628d715393503f6227) 122 | [ 123 | "20xx-11-14T09:56:20.8992704Z stdout: function called with params { hello: 'world' }", 124 | "20xx-11-14T09:56:20.8993178Z stderr: this is an error message" 125 | ] 126 | 127 | Activation: 'logs' (becbb9b0c37f45f98bb9b0c37fc5f9fc) 128 | [ 129 | "20xx-11-14T09:56:44.6961581Z stderr: this is an error message", 130 | "20xx-11-14T09:56:44.6964147Z stdout: function called with params { hello: 'world' }" 131 | ] 132 | ``` 133 | 134 | {% hint style="success" %} 135 | As you can see, activation logs provide critical insight into your functions when running within the ICF service. Next, let's explore how we can call other actions from an action allowing for function reuse. 136 | {% endhint %} 137 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex2-managing-actions-with-packages/README.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Manage actions with packages 21 | 22 | This exercise will introduce the concepts needed to create and use **packages** with IBM Cloud Functions (ICF). Packages are named entities in ICF that allow you to logically group similar actions as well as allow them to share parameters. 23 | 24 | Once you have completed this exercise, you will have: 25 | 26 | * Learned how to find public packages. 27 | * Used public package actions and bindings. 28 | * Created and shared your own custom package. 29 | 30 | Once this exercise is finished, you will be able to create and share actions using packages within ICF! 31 | 32 | ## Background 33 | 34 | In ICF, you can use packages to bundle together related actions and even share them with others. It is important to note that: 35 | 36 | * Packages can only contain actions. Triggers and rules are **not** supported at the moment. 37 | 38 | * Package nesting is **not** allowed, meaning packages cannot contain other packages. 39 | 40 | Packages also support parameters which are automatically passed into packaged actions during invocations as **default parameter values** when none are provided. 41 | 42 | {% hint style="tip" %} 43 | Package parameters provide a convenient method to manage service credentials needed with multiple actions. 44 | {% endhint %} 45 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex2-managing-actions-with-packages/REVIEW.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Review: Manage actions with packages 21 | 22 | 1. You can invoke actions in public packages as if they were normal actions. 23 | 24 | (x) True 25 | (!) False 26 | 27 | [explanation] 28 | True. You can invoke it and pass its parameters on invocation just like a normal action. 29 | [explanation] 30 | 31 | 2. You can provide default parameters to an action in a public package just as you would a normal action. 32 | 33 | (!) True 34 | (x) False 35 | 36 | [explanation] 37 | False. The action from the public package needs to be bound to a logical name within a local namespace before default parameters can be applied to it. 38 | [explanation] 39 | 40 | 3. If you bind a parameter value to a package, that value cannot be overridden on invocation. 41 | 42 | (!) True 43 | (x) False 44 | 45 | [explanation] 46 | False. The parameter value on invocation always overrides those on the package binding. 47 | [explanation] 48 | 49 | 4. After creating a custom package as private, you can update the package to make it public. 50 | 51 | (x) True 52 | (!) False 53 | 54 | [explanation] 55 | True. You simply need to update the package using the --shared flag and with a value of yesvalue. 56 | For example: 57 |

ibmcloud fn package update custom --shared yes

58 | [explanation] 59 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex3-connecting-actions-to-event-sources/README.md: -------------------------------------------------------------------------------- 1 | # Connect actions to event sources 2 | 3 | This exercise introduces concepts like **triggers** and **rules** used by the platform to connect events from event providers and sources to **actions**. If you recall, the _Trigger_ and _Rule_ entities were shown as part of the ICF programming model in the previous chapter. 4 | 5 | Once you have completed this exercise, you will have: 6 | 7 | * Learned how event sources are integrated into the IBM Cloud Functions (ICF) platform. 8 | * Created example triggers and bound to actions using rules. 9 | * Tested connecting triggers to external event sources. 10 | 11 | Once this exercise is finished, you can start to develop event-driven serverless applications using ICF! 12 | 13 | ## Background 14 | 15 | Serverless applications are often described as event-driven because you can connect serverless functions to external event sources, like message queues and database changes. When these external events fire, the serverless functions are automatically invoked, without any manual intervention. 16 | 17 | In the previous example, you’ve been manually invoking actions using the command line. Let's move onto connecting your actions to external event sources. OpenWhisk supports multiple external event sources like CouchDB, Apache Kafka, a cron-based scheduler, and more. 18 | 19 | Before you jump into the details, let's review some concepts which explain how this feature works in Apache OpenWhisk. 20 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex3-connecting-actions-to-event-sources/REVIEW.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Review: Connect actions to event sources 21 | 22 | 1. What is a trigger? 23 | 24 | ( ) An API that invokes a function 25 | ( ) A network connection between an event source and a function 26 | (x) A named channel for a class of events 27 | ( ) Event data that is sent to functions as key-value pairs 28 | 29 | [explanation] 30 | Triggers are named channels for classes or kinds of events sent from event sources. 31 | [explanation] 32 | 33 | 2. What is the purpose of a rule? 34 | 35 | ( ) associates multiple triggers with a single action 36 | (x) associates a single trigger with a single action 37 | ( ) associates a single trigger with multiple actions 38 | 39 | [explanation] 40 | Rules are used to associate one trigger with one action. After this kind of association is created, each time a trigger event is fired, the action is invoked. 41 | [explanation] 42 | 43 | 3. Rules allow you to define conditional logic that controls if an action gets invoked based upon event data. 44 | 45 | ( ) True 46 | (x) False 47 | 48 | [explanation] 49 | False. Rules are simply an association between a trigger and an action indicating that event data coming from a trigger should fire an associated action. It is either enabled or disabled. 50 | [explanation] 51 | 52 | 4. Multiple actions can be fired from a single trigger. 53 | 54 | (!) Incorrect 55 | (x) Correct 56 | 57 | [explanation] 58 | Correct. Multiple actions can be connected to the same trigger using separate rules. This allows a single event to cause many parallel serverless actions to begin processing the same data in different ways at the same time. 59 | [explanation] 60 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex3-connecting-actions-to-event-sources/concepts.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Concepts 21 | 22 | In this section you will learn about using two components of the IBM Cloud Functions (ICF) programming model called `triggers` and `rules` which are used to associate event data with your `actions`. 23 | 24 | ## Triggers 25 | 26 | Triggers are a named channel for a class of events. The following are examples of triggers: 27 | 28 | * A trigger of location update events 29 | * A trigger of document uploads to a website 30 | * A trigger of incoming emails 31 | 32 | Triggers can be fired, or activated, by using a dictionary of key-value pairs. Sometimes this dictionary is referred to as the normalized, internal event. However, these normalized events are often a representation of raw data coming from external events generated outside the serverless platform. As with actions, each firing of a trigger results in an activation ID. 33 | 34 | Triggers can be explicitly fired by a user or by an external event source. A feed is a convenient way to configure an external event source to fire trigger events that can be consumed by ICF. Examples of feeds include: 35 | 36 | * CouchDB data change feed that fires a trigger event each time a document in a database is added or modified 37 | * A Git feed that fires a trigger event for every commit to a Git repository 38 | 39 | Instances of triggers can also be fired with parameters that can be passed on to one or more actions they can be connected to using rules. 40 | 41 | --- 42 | 43 | ## Rules 44 | 45 | A rule associates one trigger with one action. Every firing of the trigger causes the corresponding action to be invoked with the trigger event as input. 46 | 47 | With the appropriate set of rules, it's possible for a single trigger event to invoke multiple actions, or for an action to be invoked as a response to events from multiple triggers. 48 | 49 | For example, consider a system with the following actions: 50 | 51 | * `classifyImage` action that detects the objects in an image and classifies them 52 | * `thumbnailImage` action that creates a thumbnail version of an image 53 | 54 | Also, suppose that there are two event sources that are firing the following triggers: 55 | 56 | * `newTweet` trigger that is fired when a new tweet is posted 57 | * `imageUpload` trigger that is fired when an image is uploaded to a website 58 | 59 | You can set up rules so that a single trigger event invokes multiple actions, and have multiple triggers invoke the same action: 60 | 61 | * `newTweet -> classifyImage` rule 62 | * `imageUpload -> classifyImage` rule 63 | * `imageUpload -> thumbnailImage` rule 64 | 65 | The three rules establish the following behavior: 66 | 67 | * Images in both tweets and uploaded images are classified 68 | * Uploaded images are classified 69 | * A thumbnail version is generated 70 | 71 | {% hint style="info" %} 72 | Triggers and rules enable the implementation of the [Observer pattern](https://en.wikipedia.org/wiki/Observer_pattern). Triggers relate state changes (events) from the subject(event source) to a list of observers (actions) when connected by a rule. 73 | {% endhint %} 74 | 75 | {% hint style="success" %} 76 | **Remember**: Rules allow you to connect a trigger to an action. That's all you need to know for now. Next you’ll learn more about using these new concepts. 77 | {% endhint %} 78 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex3-connecting-actions-to-event-sources/feeds.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Connect trigger feeds 21 | 22 | Trigger feeds allow you to connect triggers to external event sources. Event sources will fire registered triggers each time an event occurs. Here’s a [list of the packages](https://github.com/apache/incubator-openwhisk/blob/master/docs/catalog.md) currently supported on IBM Cloud Functions (ICF) which include feeds to easily connect you to services like Slack, GitHub and IBM Watson. 23 | 24 | This example shows how to use the [Alarms package](https://github.com/apache/incubator-openwhisk-package-alarms/blob/master/README.md) feed to fire a trigger every minute, which invokes an action using a rule. 25 | 26 | 1. Get a description of the feeds in the `/whisk.system/alarms` package: 27 | 28 | ```bash 29 | ibmcloud fn package get --summary /whisk.system/alarms 30 | ``` 31 | 32 | ```text 33 | package /whisk.system/alarms: Alarms and periodic utility 34 | (parameters: *apihost, *trigger_payload) 35 | feed /whisk.system/alarms/interval: Fire trigger at specified interval 36 | (parameters: minutes, startDate, stopDate) 37 | feed /whisk.system/alarms/once: Fire trigger once when alarm occurs 38 | (parameters: date, deleteAfterFire) 39 | feed /whisk.system/alarms/alarm: Fire trigger when alarm occurs 40 | (parameters: cron, startDate, stopDate) 41 | ``` 42 | 43 | 2. Retrieve the details for the `alarms/interval` feed: 44 | 45 | ```text 46 | ibmcloud fn action get --summary /whisk.system/alarms/interval 47 | ``` 48 | 49 | ```text 50 | action /whisk.system/alarms/interval: Fire trigger at specified interval 51 | (parameters: *apihost, *isInterval, minutes, startDate, stopDate, *trigger_payload) 52 | ``` 53 | 54 | The `/whisk.system/alarms/interval` feed has the following parameters we need to pass in: 55 | 56 | 1. `minutes`: An integer representing the length of the interval \(in minutes\) between trigger fires. 57 | 2. `trigger_payload`: The payload parameter value to set in each trigger event. 58 | 3. Create a trigger that fires every minute using this feed. 59 | 60 | ```bash 61 | ibmcloud fn trigger create everyMinute --feed /whisk.system/alarms/interval -p minutes 1 -p trigger_payload "{\"name\":\"Mork\", \"place\":\"Ork\"}" 62 | ``` 63 | 64 | ```text 65 | ok: invoked /whisk.system/alarms/interval with id b2b4c3cb38224f44b4c3cb38228f44be 66 | ... 67 | ok: created trigger everyMinute 68 | ``` 69 | 70 | 3. Connect this trigger to the `hello` action with a new rule: 71 | 72 | ```bash 73 | ibmcloud fn rule create everyMinuteRule everyMinute hello 74 | ``` 75 | 76 | ```text 77 | ok: created rule everyMinuteRule 78 | ``` 79 | 80 | 4. Check that the action is being invoked every minute by polling for activation logs: 81 | 82 | ```bash 83 | ibmcloud fn activation poll 84 | ``` 85 | 86 | ```text 87 | Activation: 'hello' (b2fc4b00c7be4143bc4b00c7bed1431c) 88 | [] 89 | Activation: 'everyMinute' (cec7eb38739c4d4287eb38739ccd42ef) 90 | [ 91 | "{\"statusCode\":0,\"success\":true,\"activationId\":\"b2fc4b00c7be4143bc4b00c7bed1431c\",\"rule\":\"james.thomas@uk.ibm.com_dev/everyMinuteRule\",\"action\":\"james.thomas@uk.ibm.com_dev/hello\"}" 92 | ] 93 | ``` 94 | 95 | You should see activations every minute for both the trigger and the action. The action receives the parameters `{"name":"Mork", "place":"Ork"}` on every invocation. 96 | 97 | 5. Delete the trigger and rule: 98 | 99 | {% hint style="warning" %} 100 | **Important**: Be sure to delete the trigger and rule or this event will be running **forever**! 101 | {% endhint %} 102 | 103 | ```bash 104 | ibmcloud fn trigger delete everyMinute 105 | ``` 106 | 107 | ```bash 108 | ibmcloud fn rule delete everyMinuteRule 109 | ``` 110 | 111 | {% hint style="success" %} 112 | Understanding triggers and rules allows you to build event-driven applications using ICF. All you have to do is create some actions, hook up events, and let the platform take care of everything else! What could be easier? 113 | {% endhint %} 114 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex3-connecting-actions-to-event-sources/triggers.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Create triggers 21 | 22 | Triggers represent a named channel for a stream of events. 23 | 24 | 1. Let's create a trigger to send location updates by using the following: 25 | 26 | ```bash 27 | ibmcloud fn trigger create locationUpdate 28 | ``` 29 | 30 | ```text 31 | ok: created trigger locationUpdate 32 | ``` 33 | 34 | 2. You can check that the trigger has been created like this: 35 | 36 | ```bash 37 | ibmcloud fn trigger list 38 | ``` 39 | 40 | ```text 41 | triggers 42 | locationUpdate private 43 | ``` 44 | 45 | So far we have only created a named channel to which events can be fired. 46 | 47 | 3. Let's now fire the trigger by specifying its name and parameters: 48 | 49 | ```bash 50 | ibmcloud fn trigger fire locationUpdate -p name "Barry" -p place "Central City" 51 | ``` 52 | 53 | ```text 54 | ok: triggered /_/locationUpdate with id 55 | ``` 56 | 57 | The trigger was fired, but that is all we see for now. 58 | 59 | 3. Triggers also support default parameters. Firing this trigger without any parameters will pass in the default values. 60 | 61 | ```bash 62 | ibmcloud fn trigger update locationUpdate -p name "Barry" -p place "Central City" 63 | ``` 64 | 65 | ```text 66 | ok: updated trigger locationUpdate 67 | ``` 68 | 69 | Again, the trigger was fired, but nothing apparent happens (besides seeing the confirmation message). 70 | 71 | 4. Look at the details of the `locationUpdate` trigger: 72 | 73 | ```bash 74 | ibmcloud fn trigger get locationUpdate 75 | ``` 76 | 77 | ```bash 78 | ok: got trigger locationUpdate 79 | { 80 | "namespace": "myNamespace", 81 | "name": "locationUpdate", 82 | "version": "0.0.2", 83 | "parameters": [ 84 | { 85 | "key": "name", 86 | "value": "Barry" 87 | }, 88 | { 89 | "key": "place", 90 | "value": "Central City" 91 | } 92 | ], 93 | "limits": {}, 94 | "publish": false 95 | ... 96 | } 97 | ``` 98 | 99 | The `locationUpdate` trigger will now include these parameters using the default values supplied whenever fired. 100 | 101 | {% hint style="warning" %} 102 | Events you fire to the `locationUpdate` trigger currently do not do anything. To be useful, you need to create a rule that associates the trigger with an action. 103 | {% endhint %} 104 | 105 | {% hint style="success" %} 106 | Let's continue by connecting actions to triggers using rules. 107 | {% endhint %} 108 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex4-exposing-apis-from-actions/README.md: -------------------------------------------------------------------------------- 1 | # Expose actions as APIs 2 | 3 | This exercise shows you how to create public HTTP endpoints from IBM Cloud Functions (ICF) actions. You will learn how to create web actions and use the integrated API gateway. 4 | 5 | Once you have completed this exercise, you will have: 6 | 7 | * Learned how to expose your actions as HTTP endpoints. 8 | * Created numerous examples of web actions. 9 | * Enabled API Gateway integration, including authentication and rate-limiting. 10 | 11 | Once this exercise is finished, you will be able to create scalable HTTP accessible APIs for actions using ICF! 12 | 13 | ## Background 14 | 15 | Serverless applications are a great solution for building public API endpoints. Developers are now building serverless web applications by hosting their static files on a CDN and then using serverless platforms for their APIs. 16 | 17 | OpenWhisk has a comprehensive RESTful API for the platform that allows you to invoke actions using authenticated HTTP requests. However, if you want to build APIs for public web sites or mobile applications, the authentication credentials will need embedding in client-side files. This is a terrible idea (for obvious reasons), but don't panic! 18 | 19 | {% hint style="tip" %} 20 | ICF has a solution for creating public APIs to invoke your actions without exposing credentials. 21 | {% endhint %} 22 | 23 | First, let's review some concepts which explain how this feature works in Apache OpenWhisk. 24 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex4-exposing-apis-from-actions/REVIEW.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Review: Expose APIs from actions 21 | 22 | 1. Any action can be made accessible on the web by simply setting the flag --web to true. 23 | 24 | (x) True 25 | (!) False 26 | 27 | [explanation] 28 | True. Making your actions web accessible using IBM Cloud Functions (ICF) is really that easy. 29 | [explanation] 30 | 31 | 2. Functions that are web actions need to parse the raw HTTP request header to obtain query parameters. 32 | 33 | (!) True 34 | (x) False 35 | 36 | [explanation] 37 | False. Web actions are provided all HTTP request information as parsed input arguments to their function, including the HTTP query parameters. The parameters are provided as an unparsed string value for the __ow_query_ parameter so you will still need to parse the individual parameters from it. 38 | [explanation] 39 | 40 | 3. Which command would you use to retrieve the HTTP endpoint for a web action? 41 | 42 | [!] ibmcloud fn api get <action_name> --url 43 | [x] ibmcloud fn action get <action_name> --url 44 | [ ] ibmcloud fn api get <action_name> --http 45 | [ ] ibmcloud fn action get <action_name> --http 46 | 47 | [explanation] 48 | The action get retrieves the full action record which will include the URL. Supplying the --url flag limits the result to just the HTTP endpoint value assigned to the action. 49 | [explanation] 50 | 51 | 4. If you have a web action that returns a JSON object, the caller must append .json to the web action's URL to get a successful response. 52 | 53 | (!) True 54 | (x) False 55 | 56 | [explanation] 57 | Alternatively, the function can manually set the content-type in the HTTP response header. The caller can then call the URL of the web action without modification. 58 | [explanation] 59 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex4-exposing-apis-from-actions/concepts.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Concepts 21 | 22 | ## Web actions 23 | 24 | Cloud Function actions can be annotated with a special flag, `--web true`, at creation to convert them into [web actions](https://cloud.ibm.com/docs/openwhisk?topic=cloud-functions-actions_web). The result is the corresponding creation of a public URL that can be used to trigger the action from any web app. 25 | 26 | Web actions can then be invoked via HTTP requests without user authentication where the HTTP request parameters are automatically converted in event parameters. Web actions are able to control the HTTP response headers and body to support any content types, manage cookies, and perform HTTP redirects directly. 27 | 28 | A few benefits of using web actions include: 29 | 30 | - Invoke a web action from anywhere without defining a trigger or a rule 31 | - Accessible through a REST interface without the need for credentials 32 | - Supports any `content-type` on an HTTP response, including HTML, XML, SVG, PNG, and more, with intelligent defaults for JSON payloads 33 | - Supports any type of HTTP method including GET, POST (the default), PUT, PATCH, and DELETE, as well as HEAD and OPTIONS 34 | 35 | {% hint style="tip" %} 36 | If you want to implement user authentication, rate limiting, request routing, or if you are building high traffic and enterprise APIs, the better choice is to use the Cloud Functions API Gateway features described in the next section. 37 | {% endhint %} 38 | 39 | ## API Gateway 40 | 41 | Cloud Functions comes with an integrated API Gateway service. This allows you to create new HTTP APIs which map incoming requests to actions. 42 | 43 | The API Gateway handles capabilities like routing based on request properties \(URI paths and HTTP method\), user authentication, rate limiting, and more. You do not need to implement this feature within the web action code. 44 | 45 | {% hint style="warning" %} 46 | Several of the extended features described above, along with [support of the OpenAPI Specification](https://github.com/apache/openwhisk-apigateway#API) or "Swagger", are quite deep and outside of the scope of this course. 47 | {% endhint %} 48 | 49 | {% hint style="info" %} 50 | Find out more about [API Gateway commands](https://cloud.ibm.com/docs/openwhisk?topic=cloud-functions-cli-plugin-functions-cli#cli_api) for Cloud Functions. 51 | {% endhint %} 52 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex4-exposing-apis-from-actions/images/atom.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex4-exposing-apis-from-actions/other_apis.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Other Endpoints 21 | 22 | This is a supplementary document showing the creation of API endpoints for the web actions created in a previous section. This is not mandatory, but is included for completeness. 23 | 24 | ## HTML Endpoint 25 | 26 | 1. Create the endpoint for the `html` action 27 | 28 | ```bash 29 | ibmcloud fn api create /myapi /html get html --response-type http 30 | ``` 31 | 32 | ```bash 33 | ok: created API /myapi/html GET for action /_/html 34 | https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/d9903f40439f1a268b7dcbac42a389cdde605f3f3bef57f69789be6df438361e/myapi/html 35 | ``` 36 | 37 | {% hint style="success" %} 38 | **While the content-type of the response is text/html, we are still using a response type of http and not html!** 39 | {% endhint %} 40 | 41 | 2. Check the endpoints output. You can copy/paste the url into your browser of choice to see the html rendered and curl it to see the raw html text. 42 | 43 | ```bash 44 | curl "https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/d9903f40439f1a268b7dcbac42a389cdde605f3f3bef57f69789be6df438361e/myapi/html" 45 | ``` 46 | 47 | ```html 48 |

Hello World!

49 | ``` 50 | 51 | ## SVG Endpoint 52 | 53 | 1. Create the endpoint for the `atom` svg action 54 | 55 | ```bash 56 | ibmcloud fn api create /myapi /atom get atom --response-type http 57 | ``` 58 | 59 | ```bash 60 | ok: created API /myapi/atom GET for action /_/atom 61 | https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/d9903f40439f1a268b7dcbac42a389cdde605f3f3bef57f69789be6df438361e/myapi/atom 62 | ``` 63 | 64 | 2. Test out the action by copy/pasting the endpoint into your browser of choice. 65 | 66 | _What do you see?_ 67 | 68 | ## Creating an Endpoint with an PUT HTTP method 69 | 70 | 1. Finally we create an HTTP `put` method for the manual JSON action 71 | 72 | ```bash 73 | ibmcloud fn api create /myapi /manual put manual --response-type json 74 | ``` 75 | 76 | ```bash 77 | ok: created API /myapi/manual PUT for action /_/manual 78 | https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/d9903f40439f1a268b7dcbac42a389cdde605f3f3bef57f69789be6df438361e/myapi/manual 79 | ``` 80 | 81 | 2. Test the output of the PUT action 82 | 83 | ```bash 84 | curl -XPUT "https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/d9903f40439f1a268b7dcbac42a389cdde605f3f3bef57f69789be6df438361e/myapi/manual\?hello\=world" 85 | ``` 86 | 87 | ```json 88 | { 89 | "body": { 90 | "__ow_method": "put", 91 | "__ow_path": "", 92 | "hello": "world" 93 | }, 94 | "headers": { 95 | "Content-Type": "application/json" 96 | }, 97 | "statusCode": 200 98 | } 99 | ``` 100 | 101 | 3. Test that a GET request does not work since we have not set up a GET endpoint 102 | 103 | ```bash 104 | curl -XGET "https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/d9903f40439f1a268b7dcbac42a389cdde605f3f3bef57f69789be6df438361e/myapi/manual\?hello\=world" 105 | ``` 106 | 107 | ```json 108 | {"status":404,"message":"Error: Whoops. Verb not supported."} 109 | ``` 110 | 111 | You can define more than one HTTP method for a single endpoint, so it is possible to have different methods execute different web actions on the same endpoint. 112 | 113 | {% hint style="success" %} 114 | 🎉 **Congrats on successfully creating Serverless APIs!** As you can see, exposing and managing Serverless APIs takes minimal effort using IBM Cloud Functions and allows you full access control and use of the OpenAPI specification! 115 | {% endhint %} 116 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/README.md: -------------------------------------------------------------------------------- 1 | # Use the Web User Interface (Web UI) 2 | 3 | This exercise will introduce the [IBM Cloud Functions Web UI](https://cloud.ibm.com/functions/). This application helps to manage your IBM Cloud Functions (ICF) applications from a web browser, rather than using the command line. 4 | 5 | Once you have completed this exercise, you will: 6 | 7 | * Understand how to find and use the ICF Web UI within IBM Cloud 8 | * Have performed the same tasks within the web UI as you did from the CLI 9 | 10 | Once this exercise is finished, you will be able to use the Web UI to build and manage serverless applications on IBM Cloud! 11 | 12 | ## Background 13 | 14 | ICF comes with a Web UI to help developers manage their serverless applications. Common development tasks such as creating actions, monitoring invocations, setting up triggers, and more, can all be achieved using this web application. The web application is custom to IBM Cloud and is **not** part of the open source Apache OpenWhisk project. 15 | 16 | It can often be quicker to use the Web UI for certain development tasks, rather than typing repetitive CLI commands. The Web UI integrates with the IBM Cloud interface, making it easy to provision and connect new cloud services to your applications. 17 | 18 | This exercise introduces the different features of the IBM Cloud Web UI. 19 | 20 | ## Navigate to the ICF Homepage 21 | 22 | 1. Open the [IBM Cloud homepage](https://cloud.ibm.com/). 23 | 2. Click the hamburger menu icon in the top left corner to show the menu. 24 | 25 | ![IBM Cloud hamburger menu](images/101-ex5-ibmcloud-dashboard-top-menu.png) 26 | 27 | 3. Click "Functions" in the list to open the [ICF homepage](https://cloud.ibm.com/functions/). 28 | 29 | ![IBM Cloud Functions service](images/101-ex5-ibmcloud-service-dropdown.png) 30 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/REVIEW.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Review: IBM Cloud Functions (ICF) Web User Interface (Web UI) 21 | 22 | 1. When using the ICF Web UI, you can accomplish almost everything you can using the CLI. 23 | 24 | (x) True 25 | (!) False 26 | 27 | [explanation] 28 | True. The intent of the Web UI is to provide functional equivalency to the that provided by the CLI. In fact, the Web UI actually provides simplified access to other IBM Cloud services such as Alarms, Cloudant, monitoring, and logging, that are often much harder to utilize from the command line. 29 | [explanation] 30 | 31 | 2. The ICF Web UI provides access to logs and action metrics. 32 | 33 | (x) True 34 | (!) False 35 | 36 | [explanation] 37 | True. The **monitor** feature of the Web UI provides an easy means to view recent activations of actions and triggers over periods of time. The **logging** feature can be used to automatically send complete activation records to IBM Clouds Observability service for long term retention and analysis alongside all your other IBM Cloud events. 38 | [explanation] 39 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/actions.md: -------------------------------------------------------------------------------- 1 | # Managing actions 2 | 3 | Using the web UI, you can easily create, edit, invoke and manage actions within packages for different IBM Cloud namespaces and regions. 4 | 5 | ## List actions for a namespace and region 6 | 7 | 1. Select "Actions" from the left-hand menu panel on the IBM Cloud **Functions** homepage which will display the [Management page for actions](https://cloud.ibm.com/functions/actions). It shows actions created within the selected IBM Cloud namespace and region. 8 | 9 | The following screenshot shows a listing of actions created in the `test-iam-namespace` namespace in the `Dallas` region: 10 | 11 | ![action listing page](images/101-ex5-action-list.png) 12 | 13 | 2. Click on the name of the `hello` action to move to the action details page. 14 | 15 | ![Select an action from list](images/101-ex5-action-list-select.png) 16 | 17 | ## Details overview 18 | 19 | The action details page shows properties for the chosen action. 20 | 21 | For actions written in a supported language runtime, a source code editor with the action code is displayed. It allows users to make live changes and publish them making them immediately available to users. 22 | 23 | ![action details page](images/101-ex5-action-details.png) 24 | 25 | Using the menu on the left-hand side, different properties for the action can be accessed and modified: 26 | 27 | * **Code** shows action source code in editor. 28 | * **Parameters** shows default parameters for the action. 29 | * **Runtime** shows the action runtime, timeout value, and memory limit. 30 | * **Endpoints** allow you to enable the action as a web action, and/or raw HTTP action and shows its HTTP endpoint. 31 | * **Connected triggers** shows the triggers the action is connected to. 32 | * **Enclosing sequences** shows sequences which use this action. 33 | 34 | You can explore these options later at your convenience. 35 | 36 | ## Invoke actions 37 | 38 | Let's see what happens when we invoke the selected action from the details page. 39 | 40 | 1. Click the "Invoke" button to invoke the action and display the resulting activation record. 41 | 42 | ![Invoke an action](images/101-ex5-action-invoke.png) 43 | 44 | as you can see the results show that output of the action with the default `location` parameter applied. 45 | 46 | Next, let's invoke the action with a value for the `name` parameter. 47 | 48 | 2. Click the "Invoke with parameters" button. 49 | 50 | ![Invoke an action with parameters](images/101-ex5-action-invoke-with-params.png) 51 | 52 | 3. Update JSON object with the `name` input parameter and click "Apply". 53 | 54 | ![Change action input parameters](images/101-ex5-action-change-params.png) 55 | 56 | 4. Click "Invoke" again. 57 | 58 | What do you see in the `results` of the activation record for this invocation? 59 | 60 | ![Invoke action with parameters](images/101-ex5-action-invoke-with-name-param.png) 61 | 62 | The activation result should show the `name` parameter value was successfully passed into the action. 63 | 64 | ## Create new action 65 | 66 | 1. Return to the [action listing page](https://cloud.ibm.com/functions/actions) using the `Actions` breadcrumb in the top-left of the page. 67 | 68 | ![Return to action listing](images/101-ex5-action-breadcrumb.png) 69 | 70 | 2. Select the "Create" button from the page. 71 | 72 | ![Create a new action](images/101-ex5-action-create.png) 73 | 74 | 3. Click on "Action" from the "Create" entity list. 75 | 76 | ![Create an action](images/101-ex5-entity-create-action.png) 77 | 78 | 4. Fill in the `hello2` for the "Action name" and Click "Create". 79 | 80 | The "Runtime" dropdown should already be defaulted to the latest Node.js runtime version. 81 | 82 | ![Create an action](images/101-ex5-action-create-new.png) 83 | 84 | You should now see your `hello2` action in the action details page. By default, all new actions in the web UI are pre-filled with a "hello world" function for the chosen language runtime: 85 | 86 | ![Action editor with new action](images/101-ex5-action-create-new-editor.png) 87 | 88 | from here you can modify the source code to have any function you like! 89 | 90 | {% hint style="success" %} 91 | Well done! You now can use the web UI to create and manage new actions as you did in the CLI. 92 | {% endhint %} 93 | -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-breadcrumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-breadcrumb.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-change-params.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-change-params.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-change-params.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-change-params.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-create-new-editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-create-new-editor.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-create-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-create-new.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-create-new.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-create-new.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-create.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-details.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-details.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-details.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-invoke-with-name-param.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-invoke-with-name-param.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-invoke-with-name-param.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-invoke-with-name-param.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-invoke-with-params.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-invoke-with-params.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-invoke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-invoke.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-invoke.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-invoke.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-list-select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-list-select.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-list.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-list.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-action-list.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-breadcrumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-breadcrumb.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-create-basic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-create-basic.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-create-final.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-create-final.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-create-final.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-create-final.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-create-operation-modal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-create-operation-modal.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-create-operation-modal.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-create-operation-modal.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-create-operation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-create-operation.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-create.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-create.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-details.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-details.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-details.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-greeting-explore-operation-tryit-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-greeting-explore-operation-tryit-result.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-greeting-explore-operation-tryit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-greeting-explore-operation-tryit.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-greeting-explore-operation-tryit.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-greeting-explore-operation-tryit.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-greeting-explore-operation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-greeting-explore-operation.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-greeting-explore-operation.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-greeting-explore-operation.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-greeting-explore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-greeting-explore.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-greeting-explore.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-greeting-explore.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-list-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-list-create.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-list.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-list.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-api-list.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-entity-create-action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-entity-create-action.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-entity-create-trigger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-entity-create-trigger.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-entity-create.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-entity-create.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-ibmcloud-dashboard-top-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-ibmcloud-dashboard-top-menu.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-ibmcloud-service-dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-ibmcloud-service-dropdown.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-monitoring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-monitoring.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-breadcrumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-breadcrumb.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-connect-action-add-select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-connect-action-add-select.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-connect-action-add-select.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-connect-action-add-select.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-connect-action-add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-connect-action-add.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-connect-action-add.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-connect-action-add.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-connect-action-complete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-connect-action-complete.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-connect-action-existing-add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-connect-action-existing-add.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-connect-action-existing-add.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-connect-action-existing-add.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-create-configure-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-create-configure-create.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-create-configure-name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-create-configure-name.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-create-configure.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-create-configure.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-create-type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-create-type.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-create-type.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-create-type.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-create.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-details.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-details.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-details.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-list-select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-list-select.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-list-select.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-list-select.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-list.png -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-list.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/images/101-ex5-trigger-list.psd -------------------------------------------------------------------------------- /101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/triggers.md: -------------------------------------------------------------------------------- 1 | # Managing triggers 2 | 3 | Let's explore how to create and connect triggers to actions within the ICF web UI. 4 | 5 | ## List triggers for a namespace and region 6 | 7 | 1. Select "Triggers" from the left-hand menu panel on the **Functions** homepage which will display the [management page for triggers](https://cloud.ibm.com/functions/triggers). It shows triggers created within the selected IBM Cloud namespace and region. 8 | 9 | The following screenshot shows a listing of triggers created in the `test-iam-namespace` namespace in the `Dallas` region: 10 | 11 | ![Trigger listing page](images/101-ex5-trigger-list.png) 12 | 13 | 2. Click on the name of the `locationUpdate` trigger to move to the trigger details page. 14 | 15 | ![Select a trigger from list](images/101-ex5-trigger-list-select.png) 16 | 17 | ## Details overview 18 | 19 | The trigger details page shows properties for the chosen trigger. 20 | 21 | ![Trigger details page](images/101-ex5-trigger-details.png) 22 | 23 | In this case, we see that the `locationUpdate` trigger is connected to two actions using the two rules we created earlier. 24 | 25 | Using the menu on the left-hand side, different properties for the trigger can be accessed and modified: 26 | 27 | * **Connected actions** shows the actions this trigger is connected to. 28 | * **Parameters** shows default parameters for the action. 29 | * **Endpoints** show details on how to fire this trigger remotely. 30 | 31 | You can explore these options later at your convenience. 32 | 33 | ## Create triggers 34 | 35 | 1. Return to the [trigger listing page](https://cloud.ibm.com/functions/triggers) using the `Triggers` breadcrumb in the top-left of the page. 36 | 37 | ![Return to trigger listing](images/101-ex5-trigger-breadcrumb.png) 38 | 39 | 2. Select the "Create" button from the page. 40 | 41 | ![Create a new trigger](images/101-ex5-trigger-create.png) 42 | 43 | 3. Click on "Trigger" from the "Create" entity list. 44 | 45 | ![Create a trigger](images/101-ex5-entity-create-trigger.png) 46 | 47 | 4. Click on "Custom Trigger". 48 | 49 | ![Select Custom Trigger](images/101-ex5-trigger-create-type.png) 50 | 51 | 5. Configure the trigger by filling in the "Trigger Name" and "Description" 52 | 53 | ![Configure trigger name and description](images/101-ex5-trigger-create-configure-name.png) 54 | 55 | 6. Click "Create" 56 | 57 | ![](images/101-ex5-trigger-create-configure-create.png) 58 | 59 | 7. Your trigger has been created, but is not yet connected to an action. Click "Add" in "Connected Actions". 60 | 61 | ![Select Custom Trigger](images/101-ex5-trigger-connect-action-add.png) 62 | 63 | 8. Let's connect it to an exiting action. Click "Select Existing". 64 | 65 | ![Select Custom Trigger](images/101-ex5-trigger-connect-action-add-select.png) 66 | 67 | 9. Select the `hello` action from the dropdown and click "Add". 68 | 69 | ![Select Custom Trigger](images/101-ex5-trigger-connect-action-existing-add.png) 70 | 71 | You should now see your new trigger in the trigger details page with its connection enabled to the `hello` action: 72 | 73 | ![Select Custom Trigger](images/101-ex5-trigger-connect-action-complete.png) 74 | 75 | {% hint style="info" %} 76 | When you connect a trigger to an action, the underlying code of the web UI automatically creates a **rule** "under the covers". The rule, shown as a **Connection** in the details page, is enabled by default. 77 | {% endhint %} 78 | 79 | {% hint style="success" %} 80 | Kudos! You now can use the web UI to create and connect new triggers to actions as you did in the CLI. 81 | {% endhint %} 82 | -------------------------------------------------------------------------------- /101-workshop-nodejs/source/action/javascript/asyncAction.js: -------------------------------------------------------------------------------- 1 | function main(args) { 2 | return new Promise(function(resolve, reject) { 3 | setTimeout(function() { 4 | resolve({ done: true }); 5 | }, 2000); 6 | }) 7 | } 8 | -------------------------------------------------------------------------------- /101-workshop-nodejs/source/action/javascript/atom.js: -------------------------------------------------------------------------------- 1 | // The SVG XML image source has been base64 encoded in the "body" param below: 2 | function main() { 3 | return { headers: { 'Content-Type': 'image/svg+xml', 'Cache-Control': 'No-Store' }, 4 | statusCode: 200, 5 | body: `PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii01MiAtNTMgMTAwIDEwMCIgc3Ryb2tlLXdpZHRoPSIyIj4NCiA8ZyBmaWxsPSJub25lIj4NCiAgPGVsbGlwc2Ugc3Ryb2tlPSIjNjY4OTlhIiByeD0iNiIgcnk9IjQ0Ii8+DQogIDxlbGxpcHNlIHN0cm9rZT0iI2UxZDg1ZCIgcng9IjYiIHJ5PSI0NCIgdHJhbnNmb3JtPSJyb3RhdGUoLTY2KSIvPg0KICA8ZWxsaXBzZSBzdHJva2U9IiM4MGEzY2YiIHJ4PSI2IiByeT0iNDQiIHRyYW5zZm9ybT0icm90YXRlKDY2KSIvPg0KICA8Y2lyY2xlICBzdHJva2U9IiM0YjU0MWYiIHI9IjQ0Ii8+DQogPC9nPg0KIDxnIGZpbGw9IiM2Njg5OWEiIHN0cm9rZT0id2hpdGUiPg0KICA8Y2lyY2xlIGZpbGw9IiM4MGEzY2YiIHI9IjEzIi8+DQogIDxjaXJjbGUgY3k9Ii00NCIgcj0iOSIvPg0KICA8Y2lyY2xlIGN4PSItNDAiIGN5PSIxOCIgcj0iOSIvPg0KICA8Y2lyY2xlIGN4PSI0MCIgY3k9IjE4IiByPSI5Ii8+DQogPC9nPg0KPC9zdmc+` 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /101-workshop-nodejs/source/action/javascript/empty.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/101-workshop-nodejs/source/action/javascript/empty.js -------------------------------------------------------------------------------- /101-workshop-nodejs/source/action/javascript/funcs.js: -------------------------------------------------------------------------------- 1 | function split(params) { 2 | var text = params.text || "" 3 | var words = text.split(' ') 4 | return { words: words } 5 | } 6 | 7 | function reverse(params) { 8 | var words = params.words || [] 9 | var reversed = words.map(word => word.split("").reverse().join("")) 10 | return { words: reversed } 11 | } 12 | 13 | function join(params) { 14 | var words = params.words || [] 15 | var text = words.join(' ') 16 | return { text: text } 17 | } 18 | 19 | function fail (params) { 20 | if (params.fail) { 21 | throw new Error("stopping sequence and returning.") 22 | } 23 | 24 | return params 25 | } 26 | 27 | function end (params) { 28 | return { message: "sequence finished." } 29 | } 30 | -------------------------------------------------------------------------------- /101-workshop-nodejs/source/action/javascript/hello-html.js: -------------------------------------------------------------------------------- 1 | function main() { 2 | return { 3 | headers: { 4 | 'Content-Type': 'text/html' 5 | }, 6 | statusCode: 200, 7 | body: '

hello

' } 8 | } 9 | -------------------------------------------------------------------------------- /101-workshop-nodejs/source/action/javascript/hello-person.js: -------------------------------------------------------------------------------- 1 | function main(params) { 2 | return {payload: 'Hello, ' + params.person.name + ' from ' + params.person.place}; 3 | } 4 | -------------------------------------------------------------------------------- /101-workshop-nodejs/source/action/javascript/hello.js: -------------------------------------------------------------------------------- 1 | // function main() { 2 | // return {payload: 'Hello world'}; 3 | // } 4 | 5 | function main(params) { 6 | return {payload: 'Hello, ' + params.name + ' from ' + params.place}; 7 | } 8 | -------------------------------------------------------------------------------- /101-workshop-nodejs/source/action/javascript/html.js: -------------------------------------------------------------------------------- 1 | function main() { 2 | let html = '

Hello World!

' 3 | return { headers: { "Content-Type": "text/html" }, 4 | statusCode: 200, 5 | body: html }; 6 | } -------------------------------------------------------------------------------- /101-workshop-nodejs/source/action/javascript/identity.js: -------------------------------------------------------------------------------- 1 | function main(args) { return args; } 2 | -------------------------------------------------------------------------------- /101-workshop-nodejs/source/action/javascript/manual.js: -------------------------------------------------------------------------------- 1 | function main(params) { 2 | return { 3 | statusCode: 200, 4 | headers: { 'Content-Type': 'application/json' }, 5 | body: params 6 | }; 7 | } -------------------------------------------------------------------------------- /101-workshop-nodejs/source/action/javascript/proxy.js: -------------------------------------------------------------------------------- 1 | var openwhisk = require('openwhisk'); 2 | 3 | function main(params) { 4 | if (params.password !== 'secret') { 5 | throw new Error("Password incorrect!") 6 | } 7 | 8 | var ow = openwhisk(); 9 | return ow.actions.invoke({name: "hello", blocking: true, result: true, params: params}) 10 | } 11 | -------------------------------------------------------------------------------- /101-workshop-nodejs/source/action/javascript/redirect.js: -------------------------------------------------------------------------------- 1 | function main() { 2 | return { 3 | headers: { location: "https://openwhisk.apache.org/" }, 4 | statusCode: 302 5 | }; 6 | } 7 | -------------------------------------------------------------------------------- /101-workshop-nodejs/source/action/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Frodo", 3 | "place": "the Shire" 4 | } 5 | -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/README.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Using Event Providers 21 | 22 | This section contains several step-by-step mini-workshops that teach you how to connect your Actions using Feeds, Triggers and Rules to real world services. 23 | 24 | The following 25 | 26 | * **[GitHub](github/README.md)** Learn how to trigger an action whenever someone commits new code to a repository. 27 | -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/alarms/README.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Connecting Alarm events to actions 21 | 22 | ![Cloud Functions Alarm Trigger](images/cloud-functions-alarm-trigger.png) 23 | 24 | In this example, we will show how to automatically trigger an IBM Cloud Functions action whenever an alarm is configured using the built-in [Alarms event provider](https://github.com/apache/openwhisk-catalog/tree/master/packages/alarms) package. 25 | 26 | ## Prerequisites 27 | 28 | * _None_ 29 | 30 | ## Using the Alarms package 31 | 32 | In this exercise, we use the "built-in" [`/whisk.system/alarms`](https://github.com/apache/openwhisk-catalog/tree/master/packages/alarms) package offers a convenient way to use the [GitHub APIs](https://developer.github.com/) in order to create a webhook that can generate events that can fire Cloud Functions triggers. 33 | 34 | You can get a summary of the package, its single feed action called `webhook`and their parameters: 35 | 36 | ```bash 37 | ibmcloud fn package get --summary /whisk.system/alarms 38 | ``` 39 | 40 | ```bash 41 | package /whisk.system/alarms: Alarms and periodic utility 42 | (parameters: *apihost, *trigger_payload) 43 | feed /whisk.system/alarms/interval: Fire trigger at specified interval 44 | (parameters: minutes, startDate, stopDate) 45 | feed /whisk.system/alarms/once: Fire trigger once when alarm occurs 46 | (parameters: date, deleteAfterFire) 47 | feed /whisk.system/alarms/alarm: Fire trigger when alarm occurs 48 | (parameters: cron, startDate, stopDate, timezone) 49 | 50 | ``` 51 | 52 | ## Setting up GitHub 53 | 54 | We will need to generate a token that the `/whisk.system/github` package will need to have permission be able to create a webhook that can fire a trigger. 55 | 56 | 1. Generate a GitHub [personal access token](https://github.com/settings/tokens). 57 | 58 | **Important!** _Please pay attention to these 2 things when [creating your personal access token](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line)._ 59 | 60 | * Select the following **scopes**: 61 | * **repo**: **repo:status** to allow access to commit status. 62 | ![Token Repo. Access Scope](images/github-access-scope-repo.png) 63 | 64 | * **admin:repo_hook**: **write:repo_hook** to allow the feed action to create your webhook. 65 | ![Token WebHook Access Scope](images/github-access-scope-repo-hook.png) 66 | * Make sure to copy your new personal access token when shown. GitHub will not let you see it again once you leave the page! 67 | * If you forgot your token, you can find it by name: [https://github.com/settings/tokens](https://github.com/settings/tokens) and press the **"Regenerate token"** button to create a new one. 68 | 69 | 1. Verify your personal access token was created successfully with the proper scopes: [https://github.com/settings/tokens](https://github.com/settings/tokens) 70 | 71 | ## Binding the GitHub package with your GitHub account information 72 | 73 | **Warning!** _Before issuing the following command, make sure that you don't have any webhooks already defined for your repository or they may be overwritten when running the next command._ 74 | 75 | 1. Create a package binding named `myGit` to the `/whisk.system/github` package with your user name, repository name and personal access token. 76 | 77 | ```bash 78 | ibmcloud package bind /whisk.system/github myGit \ 79 | --param username myGitUser \ 80 | --param repository myGitRepo \ 81 | --param accessToken 2277c115d5c143b499ac31ff65b0aec8 82 | ``` 83 | 84 | Replace: 85 | * `myGitUser` with your user GitHub user name 86 | * `myGitRepo` with the directory you want to receive events for in this exercise. 87 | * `2277c115d5c143b499ac31ff65b0aec8` with the GitHub personal access token you generated above 88 | 89 | _**Note** by binding your github information to the package, you don't need to specify the values each time that you call the feed action (i.e., `webhook`)._ 90 | 91 | 92 | {% hint style="success" %} 93 | 🎉**Congratulations!** _TBD_🎉 94 | {% endhint %} 95 | 96 | # References 97 | 98 | * For a better general understanding of how Triggers work see _[IBM Cloud Functions - Your first Action, Trigger, and Rule](https://github.com/IBM/ibm-cloud-functions-action-trigger-rule)_ in IBM open source. 99 | * To see the code pattern this course is based upon see _[Triggering IBM Cloud Functions with scheduled tasks](https://github.com/IBM/ibm-cloud-functions-scheduled-tasks)_ in IBM open source. 100 | * Apache OpenWhisk's [Alarms package](https://github.com/apache/openwhisk-catalog/tree/master/packages/alarms) documentation has a more terse (yet canonical) description of the `/whisk.system/alarms` package. 101 | -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/alarms/images/cloud-functions-alarm-trigger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/alarms/images/cloud-functions-alarm-trigger.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/cloudant-dashboard-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/cloudant-dashboard-link.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/create-database.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/create-database.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/new-document.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/new-document.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/new-input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/new-input.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/new-service-credentials-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/new-service-credentials-button.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/output.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/service-credentials-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/service-credentials-menu.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/view-service-credentials.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cloudant/images/view-service-credentials.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/authorizations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/authorizations.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/create-authorizations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/create-authorizations.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/create-bucket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/create-bucket.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/create-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/create-button.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/custom-bucket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/custom-bucket.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/grant-authorization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/grant-authorization.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/new-bucket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/new-bucket.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/new-cos-instance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/new-cos-instance.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/upload-bucket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/cos/images/upload-bucket.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-access-scope-repo-hook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-access-scope-repo-hook.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-access-scope-repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-access-scope-repo.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-commit-new-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-commit-new-file.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-create-a-repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-create-a-repo.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-create-new-markdown-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-create-new-markdown-file.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-repo-created-with-readme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-repo-created-with-readme.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-repo-edit-readme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-repo-edit-readme.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-repo-save readme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/201-intermediate-courselets-nodejs/201-using-event-providers/github/images/github-repo-save readme.png -------------------------------------------------------------------------------- /201-intermediate-courselets-nodejs/README.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Intermediate workshops for NodeJS 21 | 22 | This section various intermediate mini-workshops that can be taken independently of each other depending on your interests. 23 | 24 | These intermediate workshops fall under the following categories: 25 | 26 | * **[Using Event Providers](201-using-event-providers/README.md)** Learn how to connect your Actions using Feeds, Triggers and Rules to real world services such as IBM Cloudant (NoSQL document store), IBM Cloud Object Storage (COS), GitHub, Mobile Push, Slack and more. 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # IBM Cloud Functions Workshops 21 | 22 | *Welcome to the homepage for workshops that are designed to teach you how to develop **serverless applications**, composed of loosely coupled microservice-like functions, using the [IBM Cloud Functions](https://cloud.ibm.com/functions) service. IBM Cloud Functions is based upon the [Apache OpenWhisk](https://openwhisk.apache.org/) open-source serverless platform whose initial codebase came out of IBM Research and was donated to the Apache Software Foundation (ASF).* 23 | 24 | Specifically, this repository contains various workshops for developers wishing to learn, in a step-by-step manner, how to use the IBM Cloud Functions Serverless platform using both client tooling such as the IBM Cloud Command Line Interface (CLI) as well as the IBM Cloud Web User Interface (UI). 25 | 26 | The workshops are organized incrementally, by developer experience level from beginner to expert, as well as providing independent exercises showing how to provide specific Function integrations with IBM Cloud services such as Cloudant (NoSQL), Cloud Object Storage (COS), Mobile Push Notifications and others. 27 | 28 | The workshops are organized as follows: 29 | 30 | * [**Prerequisites**](prereqs/README.md) - Provides instructions on how to sign up for IBM Cloud and the IBM Cloud Functions service, as well as the installation of the Command Line Interface (CLI) and other tooling needed for the workshops. 31 | * [**NodeJS Introductory Workshop**](101-workshop-nodejs/README.md) - 32 | 33 | ## Learn more about IBM Cloud Functions before you begin 34 | 35 | Here are some links that you may find helpful in understanding what IBM Cloud Functions can do for you: 36 | 37 | * [Getting Started on Cloud Functions](https://cloud.ibm.com/docs/openwhisk?topic=cloud-functions-getting-started) 38 | * [Cloud Functions CLI Reference](https://cloud.ibm.com/docs/cloud-functions-cli-plugin/cloud-functions-cli-plugin-functions-cli?topic=cloud-functions-cli-plugin-functions-cli) for the IBM Cloud Functions plug-in to the IBM Cloud CLI 39 | * [Cloud Functions API Documentation](https://cloud.ibm.com/apidocs/functions) 40 | * Learn how Cloud Functions supports advanced [IAM access control through the use if Namespaces](https://cloud.ibm.com/docs/openwhisk?topic=cloud-functions-namespaces#targeting-namespaces). 41 | 42 | **Note** _All workshop materials are provided under the [Apache 2 license](LICENSE)._ 43 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Table of contents 2 | 3 | * [IBM Cloud Functions Workshops](README.md) 4 | * [Prerequisites](prereqs/README.md) 5 | * [Signing up for an IBM Cloud account](prereqs/signup.md) 6 | * [Setting up the IBM Cloud CLI](prereqs/cli-setup.md) 7 | * [Installing the Cloud Functions plugin](prereqs/cloud-functions.md) 8 | * [Introductory Workshop for NodeJS](101-workshop-nodejs/README.md) 9 | * [What is Serverless?](101-workshop-nodejs/ex0-what-is-serverless/README.md) 10 | * [Definition](101-workshop-nodejs/ex0-what-is-serverless/serverless-defined.md) 11 | * [Characteristics of serverless](101-workshop-nodejs/ex0-what-is-serverless/serverless-characteristics.md) 12 | * [Pprogramming model](101-workshop-nodejs/ex0-what-is-serverless/serverless-programming-model.md) 13 | * [Deployment models](101-workshop-nodejs/ex0-what-is-serverless/serverless-deployment-models.md) 14 | * [When to apply serverless](101-workshop-nodejs/ex0-what-is-serverless/serverless-use-cases.md) 15 | * [Writing serverless applications](101-workshop-nodejs/ex0-what-is-serverless/serverless-writing-apps.md) 16 | * [Create and invoke actions](101-workshop-nodejs/ex1-creating-and-invoking-actions/README.md) 17 | * [Create and invoke actions](101-workshop-nodejs/ex1-creating-and-invoking-actions/create-invoke.md) 18 | * [Use action parameters](101-workshop-nodejs/ex1-creating-and-invoking-actions/use-parameters.md) 19 | * [Retrieving action logs](101-workshop-nodejs/ex1-creating-and-invoking-actions/retrieve-logs.md) 20 | * [Calling other actions](101-workshop-nodejs/ex1-creating-and-invoking-actions/action-proxy.md) 21 | * [Asynchronous actions](101-workshop-nodejs/ex1-creating-and-invoking-actions/async.md) 22 | * [Use action sequences](101-workshop-nodejs/ex1-creating-and-invoking-actions/ex1.2-using-action-sequences/README.md) 23 | * [Create and invoke sequences](101-workshop-nodejs/ex1-creating-and-invoking-actions/ex1.2-using-action-sequences/sequences.md) 24 | * [Manage actions with packages](101-workshop-nodejs/ex2-managing-actions-with-packages/README.md) 25 | * [Use existing packages](101-workshop-nodejs/ex2-managing-actions-with-packages/existing.md) 26 | * [Create custom packages](101-workshop-nodejs/ex2-managing-actions-with-packages/custom.md) 27 | * [Connect actions to event sources](101-workshop-nodejs/ex3-connecting-actions-to-event-sources/README.md) 28 | * [Concepts](101-workshop-nodejs/ex3-connecting-actions-to-event-sources/concepts.md) 29 | * [Create triggers](101-workshop-nodejs/ex3-connecting-actions-to-event-sources/triggers.md) 30 | * [Use Rules](101-workshop-nodejs/ex3-connecting-actions-to-event-sources/rules.md) 31 | * [Connect trigger feeds](101-workshop-nodejs/ex3-connecting-actions-to-event-sources/feeds.md) 32 | * [Expose APIs from actions](101-workshop-nodejs/ex4-exposing-apis-from-actions/README.md) 33 | * [Concepts](101-workshop-nodejs/ex4-exposing-apis-from-actions/concepts.md) 34 | * [Web actions](101-workshop-nodejs/ex4-exposing-apis-from-actions/web-actions.md) 35 | * [API Management](101-workshop-nodejs/ex4-exposing-apis-from-actions/api.md) 36 | * [Use the Web User Interface](101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/README.md) 37 | * [Managing actions](101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/actions.md) 38 | * [Managing triggers](101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/triggers.md) 39 | * [Monitoring and APIs](101-workshop-nodejs/ex5-ibm-cloud-functions-web-ui/monitoring_and_apis.md) 40 | * [Intermediate Mini-workshops for NodeJS](201-intermediate-courselets-nodejs/README.md) 41 | * [Using Event Providers](201-intermediate-courselets-nodejs/201-using-event-providers/README.md) 42 | * [Alarms](201-intermediate-courselets-nodejs/201-using-event-providers/alarms/README.md) 43 | * [Cloudant](https://github.com/IBM/ibm-cloud-functions-scheduled-tasks) 44 | * [Cloud Object Storage (COS)](https://cloud.ibm.com/docs/openwhisk?topic=cloud-functions-pkg_obstorage) 45 | * [Push Notifications](https://developer.ibm.com/patterns/serverless-functions-push-notifications/) 46 | * [GitHub](201-intermediate-courselets-nodejs/201-using-event-providers/github/README.md) 47 | * [Slack](https://cloud.ibm.com/docs/tutorials?topic=solution-tutorials-slack-chatbot-database-watson&pos=2) 48 | * [Bonus Exercises](101-workshop-nodejs/bonus-exercises/README.md) 49 | * [Calling an external API from an Async action](101-workshop-nodejs/bonus-exercises/ex1-invoking-an-async-api.md) 50 | * [Additional Topics](#) 51 | * [Action Limits](https://cloud.ibm.com/docs/openwhisk?topic=cloud-functions-limits) 52 | * [Using IAM Namespaces (Managing)](https://cloud.ibm.com/docs/openwhisk?topic=cloud-functions-namespaces) 53 | -------------------------------------------------------------------------------- /content/OW-Programming-Model-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/content/OW-Programming-Model-1.png -------------------------------------------------------------------------------- /content/OW-Programming-Model-2-Action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/content/OW-Programming-Model-2-Action.png -------------------------------------------------------------------------------- /content/OW-Programming-Model-2-All.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/content/OW-Programming-Model-2-All.png -------------------------------------------------------------------------------- /content/OW-Programming-Model-2-Feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/content/OW-Programming-Model-2-Feed.png -------------------------------------------------------------------------------- /content/OW-Programming-Model-2-Trigger-Rule.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/content/OW-Programming-Model-2-Trigger-Rule.png -------------------------------------------------------------------------------- /content/OW-Programming-Model-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/content/OW-Programming-Model-2.png -------------------------------------------------------------------------------- /content/OW-Programming-Model-2.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/content/OW-Programming-Model-2.psd -------------------------------------------------------------------------------- /iam/images/create_namespace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/iam/images/create_namespace.png -------------------------------------------------------------------------------- /iam/images/create_namespace_modal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/iam/images/create_namespace_modal.png -------------------------------------------------------------------------------- /ibm-cloud-functions-logo-transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/ibm-cloud-functions-logo-transparent.png -------------------------------------------------------------------------------- /md2html.sh: -------------------------------------------------------------------------------- 1 | node ./md2html.js -s . -c static -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cloud-functions-workshops-html", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/IBM/cloud-functions-workshops.git" 12 | }, 13 | "author": "", 14 | "license": "Apache-2.0", 15 | "bugs": { 16 | "url": "https://github.com/IBM/cloud-functions-workshops/issues" 17 | }, 18 | "homepage": "https://github.com/IBM/cloud-functions-workshops#readme", 19 | "dependencies": { 20 | "glob": "^7.1.6", 21 | "markdown-to-html": "0.0.13", 22 | "showdown": "^1.9.1", 23 | "showdown-highlight": "^2.1.3", 24 | "yargs": "^15.1.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /prereqs/README.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Prerequisites 21 | 22 | ## Setting Up a Development Environment 23 | 24 | This exercise will set up your local development environment to use IBM Cloud Functions. These steps are a prerequisite before you can start building serverless applications. 25 | 26 | _Once you have completed this exercise, you will have…_ 27 | 28 | * **Registered an IBM Cloud account.** 29 | * **Installed and configured IBM Cloud CLI tools.** 30 | * **Tested a sample IBM Cloud Functions action from the command-line.** 31 | 32 | Once this exercise is finished, we can start to develop serverless applications using IBM Cloud Functions! 33 | -------------------------------------------------------------------------------- /prereqs/cli-setup.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Setting Up the IBM Cloud CLI 21 | 22 | This section will take you step-by-step through [Getting started with the IBM Cloud CLI and Developer Tools](https://cloud.ibm.com/docs/cli?topic=cloud-cli-getting-started) using the command line option. 23 | 24 | ## Install IBM Cloud CLI 25 | 26 | We have provided the basic instructions here with screenshots, but you can find the canonical IBM Cloud Instructions here: [IBM Cloud CLI Getting Started](https://cloud.ibm.com/docs/cli?topic=cloud-cli-getting-started#step1-install-idt) 27 | 28 | Download the `ibmcloud` CLI by running the command appropriate for your operating system: 29 | 30 | #### MacOS & Linux 31 | 32 | ```bash 33 | curl -sL https://ibm.biz/idt-installer | bash 34 | ``` 35 | 36 | #### Windows 10 Pro (Powershell) 37 | 38 | Run the following as Administrator: 39 | 40 | ```bash 41 | [Net.ServicePointManager]::SecurityProtocol = "Tls12"; iex(New-Object Net.WebClient).DownloadString('https://ibm.biz/idt-win-installer') 42 | ``` 43 | 44 | {% hint style="tip" %} 45 | **Tip**: You can right-click the Windows™ PowerShell icon, and select Run as administrator. 46 | {% endhint %} 47 | 48 | ## Verify the Installation [🔗](https://cloud.ibm.com/docs/cli?topic=cloud-cli-getting-started#step2-verify-idt) 49 | 50 | Try running the help command: 51 | 52 | ```bash 53 | ibmcloud dev help 54 | ``` 55 | 56 | and see if the help instructions are printed, for example: 57 | 58 | ```bash 59 | NAME: 60 | ibmcloud dev - Create, develop, deploy, and monitor applications 61 | 62 | USAGE: 63 | ibmcloud dev command [arguments...] [command options] 64 | 65 | VERSION: 66 | 2.4.6 67 | 68 | COMMANDS: 69 | ... 70 | ``` 71 | 72 | ## Login and Configure the IBM Cloud CLI [📃](https://cloud.ibm.com/docs/cli?topic=cloud-cli-getting-started#step3-configure-idt-env) 73 | 74 | 1. Use this command to authenticate the IBM Cloud CLI with your account credentials. 75 | 76 | ```bash 77 | ibmcloud login 78 | ``` 79 | 80 | 2. Enter account credentials for your IBM Cloud account. 81 | 82 | ```bash 83 | Email> josephine.watson@gmail.com 84 | Password: ******** 85 | Authenticating... 86 | OK 87 | 88 | Targeted account Josephine Watson's Account (87a302ad58884640a45f959d3da6cc77) 89 | API endpoint: https://cloud.ibm.com 90 | Region: us-south 91 | User: josephine.watson@gmail.com 92 | Account: Josephine Watson's Account (87a302ad58884640a45f959d3da6cc77) 93 | Resource group: No resource group targeted, use 'ibmcloud target -g RESOURCE_GROUP' 94 | CF API endpoint: 95 | Org: 96 | Space: 97 | ``` 98 | 99 | _Note: If you already have created an IBM Cloud account you may be prompted to select the account you wish the IBM Cloud CLI to use:_ 100 | 101 | ```bash 102 | Select an account (or press enter to skip): 103 | Select an account: 104 | 1. Josephine Watson's Account (87a302ad58884640a45f959d3da6cc77) 105 | Enter a number> 1 106 | ``` 107 | 108 | 3. Configure your Cloud Foundry organization and space the CLI is targeting. 109 | 110 | Run the following interactive command: 111 | 112 | ```bash 113 | ibmcloud target --cf 114 | ``` 115 | 116 | ```bash 117 | Targeted Cloud Foundry (https://api.ng.bluemix.net) 118 | Targeted org josephine.watson@gmail.com 119 | Targeted space dev 120 | 121 | API endpoint: https://cloud.ibm.com 122 | Region: us-south 123 | User: josephine.watson@gmail.com 124 | Account: Josephine Watson's Account (87a302ad58884640a45f959d3da6cc77) 125 | Resource group: No resource group targeted, use 'ibmcloud target -g RESOURCE_GROUP' 126 | CF API endpoint: https://api.ng.bluemix.net (API version: 2.142.0) 127 | Org: josephine.watson@gmail.com 128 | Space: dev 129 | ``` 130 | 131 | _**Note**: If you already have already created an Namespaces, you may ne prompted to select the Namespace you wish to use as the default for the `cloud-functions` plugin._ 132 | 133 | {% hint style="success" %} 134 | 🎉 **Congratulations, you've successfully registered an IBM Cloud account and logged into the IBM Cloud CLI.** 🎉 135 | {% endhint %} 136 | -------------------------------------------------------------------------------- /prereqs/cloud-functions.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Installing the Cloud Functions Plugin 21 | 22 | This section will take you step-by-step through the [setup of the IBM Cloud Functions CLI plugin](https://cloud.ibm.com/functions/learn/cli). 23 | 24 | ## Install IBM Cloud Functions CLI plugin 25 | 26 | Use this command to install the Cloud Functions plugin for the IBM Cloud CLI. 27 | 28 | ```bash 29 | ibmcloud plugin install cloud-functions 30 | ``` 31 | 32 | ```bash 33 | Looking up 'cloud-functions' from repository 'IBM Cloud'... 34 | Plug-in 'cloud-functions 1.0.xx' found in repository 'IBM Cloud' 35 | Attempting to download the binary file... 36 | 12.93 MiB / 12.93 MiB [===========================================] 100.00% 1s 37 | 13563264 bytes downloaded 38 | Installing binary... 39 | OK 40 | Plug-in 'cloud-functions 1.0.xx' was successfully installed into /Users/Joesephine/.bluemix/plugins/cloud-functions. Use 'ibmcloud plugin show cloud-functions' to show its details. 41 | ``` 42 | 43 | ## Target a Resource Group and Namespace 44 | 45 | 1. List all available resource groups on your account: 46 | 47 | ```bash 48 | ibmcloud resource groups 49 | ``` 50 | 51 | ```bash 52 | Retrieving all resource groups under account Josephine Watson's Account as josephine.watson@gmail.com... 53 | OK 54 | Name ID Default Group State 55 | Default 2cdb253b144c4d36ae8f1c125a3ab6d5 true ACTIVE 56 | ``` 57 | 58 | 2. Target the desired resource group. In this case we target the group named `Default`: 59 | 60 | ```bash 61 | ibmcloud target -g Default 62 | ``` 63 | 64 | ```bash 65 | Targeted resource group default 66 | 67 | API endpoint: https://cloud.ibm.com 68 | Region: us-south 69 | User: josephine.watson@gmail.com 70 | Account: Josephine Watson's Account (87a302ad58884640a45f959d3da6cc77) 71 | Resource group: Default 72 | CF API endpoint: https://api.ng.bluemix.net (API version: 2.142.0) 73 | Org: josephine.watson@gmail.com 74 | Space: dev 75 | ``` 76 | 77 | 3. Verify your (default) namespace is configured to the `cloud-functions` plugin: 78 | 79 | ```bash 80 | ibmcloud fn namespace list 81 | ``` 82 | 83 | ```bash 84 | name type id 85 | josephine.watson@gmail.com_dev CF-based josephine.watson@gmail.com_dev 86 | ``` 87 | 88 | _**Note**: A default namespace should have been created for you as part of the installation and configuration of the `cloud-functions` plugin._ 89 | 90 | ## Test IBM Cloud Functions From The CLI 91 | 92 | Run the following command to invoke a test function from the command-line. 93 | 94 | ```bash 95 | ibmcloud fn action invoke whisk.system/utils/echo -p message hello --result 96 | ``` 97 | 98 | You should see that the built-in `echo` function responds with a JSON result that set the `message` key's value to "hello": 99 | 100 | ```bash 101 | { 102 | "message": "hello" 103 | } 104 | ``` 105 | 106 | {% hint style="success" %} 107 | 🎉 **Congratulations, you've successfully configured the IBM Cloud CLI for Cloud Functions development and executed your first serverless function! Let's start using the platform to create our own serverless applications...** 108 | {% endhint %} 109 | 110 | ### Using aliases for the Cloud Functions plugin 111 | 112 | The IBM Cloud Functions plugin is referenced as a sub-command under the IBM Cloud CLI by its name `cloud-functions`, but can also be referenced by the shorter aliases: 113 | 114 | - `functions` 115 | - `fn` _or_ 116 | - `wsk` 117 | 118 | {% hint style="info" %} 119 | _**Info**: The `cloud-functions` plugin provides an IBM specific implementation of the [Apache OpenWhisk CLI](https://github.com/apache/incubator-openwhisk/blob/master/docs/cli.md). This is why one of the aliases is named `wsk`. However, the IBM version supports custom credentials and configurations needed for working with the IBM Cloud and its services._ 120 | {% endhint %} 121 | 122 | ## Logging out of your IBM Cloud account 123 | 124 | {% hint style="warning" %} 125 | **Warning**: _**Do not logout of your IBM Cloud account now or you will have to redo steps you just completed!**_ 126 | {% endhint %} 127 | 128 | Some configuration data is lost every time you logout of the IBM Cloud account, or if your login expires including your default: 129 | 130 | - **Resource group** 131 | - **Namespace** 132 | 133 | If this happens, you will have to follow the steps described above to again configure these values in order to use the _IBM Cloud Functions plugin_. 134 | -------------------------------------------------------------------------------- /prereqs/images/prereq-ibm-cloud-cloud-foundry-orgs-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/prereqs/images/prereq-ibm-cloud-cloud-foundry-orgs-1.png -------------------------------------------------------------------------------- /prereqs/images/prereq-ibm-cloud-cloud-foundry-orgs-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/prereqs/images/prereq-ibm-cloud-cloud-foundry-orgs-2.png -------------------------------------------------------------------------------- /prereqs/images/prereq-ibm-cloud-registration-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/prereqs/images/prereq-ibm-cloud-registration-1.png -------------------------------------------------------------------------------- /prereqs/images/prereq-ibm-cloud-registration-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/prereqs/images/prereq-ibm-cloud-registration-2.png -------------------------------------------------------------------------------- /prereqs/images/prereq-ibm-cloud-registration-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/prereqs/images/prereq-ibm-cloud-registration-3.png -------------------------------------------------------------------------------- /prereqs/images/prereq-ibm-cloud-registration-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/prereqs/images/prereq-ibm-cloud-registration-4.png -------------------------------------------------------------------------------- /prereqs/images/prereq-ibm-cloud-registration-email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/prereqs/images/prereq-ibm-cloud-registration-email.png -------------------------------------------------------------------------------- /prereqs/signup.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Sign Up for an IBM Cloud Account 21 | 22 | You must have a valid IBM Cloud Account to complete exercises in the workshops. 23 | 24 | New IBM Cloud accounts default to a [new "lite" account version](https://www.ibm.com/cloud/free/); other [IBM Cloud pricing options](https://www.ibm.com/cloud/pricing) are available if you wish to upgrade at a later time. 25 | 26 | _This account provides free access to a subset of IBM Cloud resources, including IBM Cloud Functions. Lite accounts do not need a credit-card to sign up or expire after a set time period, i.e. 30 days._ 27 | 28 | Developers using "_Lite accounts_" are restricted to development within a single region. Accounts are automatically assigned to either `UK South` or `US South` regions depending on user profile location. 29 | 30 | _**Note** IBM Cloud Functions is [available in other regions](https://cloud.ibm.com/docs/openwhisk?topic=cloud-functions-cloudfunctions_regions) as well if you upgrade from a Lite account._ 31 | 32 | ## Create an Account 33 | 34 | 1. Open a browser window 35 | 36 | 2. Navigate to [https://cloud.ibm.com/registration](https://cloud.ibm.com/registration) 37 | 38 | 3. Fill in the registration page: 39 | 40 | ![IBM Cloud Account Registration page](images/prereq-ibm-cloud-registration-1.png) 41 | 42 | 4. Select email preferences, read the Terms and Conditions and the click the **"Create Account"** button: 43 | 44 | ![IBM Cloud Contact, Privacy and T&C](images/prereq-ibm-cloud-registration-2.png) 45 | 46 | You should be directed to verify your account email address: 47 | 48 | ![Check your email message](images/prereq-ibm-cloud-registration-3.png) 49 | 50 | 5. Look for the account confirmation email in your inbox: 51 | 52 | ![IBM Cloud Confirmation Email](images/prereq-ibm-cloud-registration-email.png) 53 | 54 | and click `Confirm account` in the email body which should take you back to IBM Cloud and display a confirmation message: 55 | 56 | ![Registration confirmed message](images/prereq-ibm-cloud-registration-4.png) 57 | 58 | 6. [Login into IBM Cloud](https://cloud.ibm.com/) using the account credentials you have registered. 59 | 60 | {% hint style="tip" %} 61 | You should be redirected there automatically after confirming the account from the email. Otherwise you can click this link: [https://cloud.ibm.com/](https://cloud.ibm.com/) 62 | {% endhint %} 63 | 64 | ## Verify Default Region 65 | 66 | {% hint style="warning" %} 67 | **Please follow these instructions** _ 68 | We know it looks boring but trust us! People often skim this part and then complain they can't login into the CLI. These instructions will save you all that inevitable confusion..._ 69 | {% endhint %} 70 | 71 | Follow these instructions to check which default region your lite account has been assigned. 72 | 73 | 1. Open the [Cloud Foundry Organizations](https://cloud.ibm.com/account/cloud-foundry) page 74 | 75 | 2. Click the organization `name` listed in the table. 76 | *Note that your organization is usually the email address you signed up with* 77 | 78 | ![Cloud Foundry Orgs.](images/prereq-ibm-cloud-cloud-foundry-orgs-1.png) 79 | 80 | 3. Locate the default organization named `dev` and check the associated "_Region_" value listed in the table. 81 | 82 | ![Cloud Foundry Org. Spaces](images/prereq-ibm-cloud-cloud-foundry-orgs-2.png) 83 | 84 | {% hint style="info" %} 85 | The value should be either `'UK South'` or `'US South'`. **Remember this as the default region value for the next step** (Installing the IBM Cloud CLI). 86 | {% endhint %} 87 | 88 | {% hint style="success" %} 89 | 🎉 **Congratulations, you've successfully registered an IBM Cloud account!** 90 | {% endhint %} 91 | -------------------------------------------------------------------------------- /presentations/101-review-questions-graphics.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/presentations/101-review-questions-graphics.pptx -------------------------------------------------------------------------------- /presentations/2020-03-09-Serverless-CC-AI-materials.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/presentations/2020-03-09-Serverless-CC-AI-materials.pptx -------------------------------------------------------------------------------- /presentations/OW-Programming-Model.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/presentations/OW-Programming-Model.pptx -------------------------------------------------------------------------------- /serverless-acclaim-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/serverless-acclaim-badge.png -------------------------------------------------------------------------------- /serverless-acclaim-badge.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/serverless-acclaim-badge.psd -------------------------------------------------------------------------------- /serverless-banner-abstract.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/serverless-banner-abstract.png -------------------------------------------------------------------------------- /serverless-banner-abstract.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/cloud-functions-workshops/6a2aeb0620283e46d5b9b59e7d4b45749fd880fa/serverless-banner-abstract.psd -------------------------------------------------------------------------------- /svg/info-i-outline-blue.plain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 35 | -------------------------------------------------------------------------------- /svg/info-i-outline-blue.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 51 | 53 | 56 | 58 | 59 | 60 | 65 | 73 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /svg/success-checkmark-outline.green.plain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 37 | -------------------------------------------------------------------------------- /svg/success-checkmark-outline.green.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 36 | 39 | 40 | 41 | 62 | 67 | 70 | 77 | 78 | 84 | 85 | 99 | 100 | -------------------------------------------------------------------------------- /svg/warning-exclaim-outline-yellow.plain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /svg/warning-exclaim-outline-yellow.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 30 | 31 | 32 | Matt Rutkowski 33 | 34 | 35 | 36 | 37 | 38 | 40 | 61 | 66 | 74 | 80 | 88 | 89 | 90 | --------------------------------------------------------------------------------