├── .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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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.
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 |
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 | 
26 |
27 | 3. Click "Functions" in the list to open the [ICF homepage](https://cloud.ibm.com/functions/).
28 |
29 | 
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 | 
12 |
13 | 2. Click on the name of the `hello` action to move to the action details page.
14 |
15 | 
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 | 
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 | 
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 | 
51 |
52 | 3. Update JSON object with the `name` input parameter and click "Apply".
53 |
54 | 
55 |
56 | 4. Click "Invoke" again.
57 |
58 | What do you see in the `results` of the activation record for this invocation?
59 |
60 | 
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 | 
69 |
70 | 2. Select the "Create" button from the page.
71 |
72 | 
73 |
74 | 3. Click on "Action" from the "Create" entity list.
75 |
76 | 
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 | 
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 | 
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 | 
12 |
13 | 2. Click on the name of the `locationUpdate` trigger to move to the trigger details page.
14 |
15 | 
16 |
17 | ## Details overview
18 |
19 | The trigger details page shows properties for the chosen trigger.
20 |
21 | 
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 | 
38 |
39 | 2. Select the "Create" button from the page.
40 |
41 | 
42 |
43 | 3. Click on "Trigger" from the "Create" entity list.
44 |
45 | 
46 |
47 | 4. Click on "Custom Trigger".
48 |
49 | 
50 |
51 | 5. Configure the trigger by filling in the "Trigger Name" and "Description"
52 |
53 | 
54 |
55 | 6. Click "Create"
56 |
57 | 
58 |
59 | 7. Your trigger has been created, but is not yet connected to an action. Click "Add" in "Connected Actions".
60 |
61 | 
62 |
63 | 8. Let's connect it to an exiting action. Click "Select Existing".
64 |
65 | 
66 |
67 | 9. Select the `hello` action from the dropdown and click "Add".
68 |
69 | 
70 |
71 | You should now see your new trigger in the trigger details page with its connection enabled to the `hello` action:
72 |
73 | 
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: '
'
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 | 
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 | 
63 |
64 | * **admin:repo_hook**: **write:repo_hook** to allow the feed action to create your webhook.
65 | 
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 | 
41 |
42 | 4. Select email preferences, read the Terms and Conditions and the click the **"Create Account"** button:
43 |
44 | 
45 |
46 | You should be directed to verify your account email address:
47 |
48 | 
49 |
50 | 5. Look for the account confirmation email in your inbox:
51 |
52 | 
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 | 
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 | 
79 |
80 | 3. Locate the default organization named `dev` and check the associated "_Region_" value listed in the table.
81 |
82 | 
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 |
8 |
35 |
--------------------------------------------------------------------------------
/svg/info-i-outline-blue.svg:
--------------------------------------------------------------------------------
1 |
2 |
81 |
--------------------------------------------------------------------------------
/svg/success-checkmark-outline.green.plain.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
37 |
--------------------------------------------------------------------------------
/svg/success-checkmark-outline.green.svg:
--------------------------------------------------------------------------------
1 |
2 |
100 |
--------------------------------------------------------------------------------
/svg/warning-exclaim-outline-yellow.plain.svg:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/svg/warning-exclaim-outline-yellow.svg:
--------------------------------------------------------------------------------
1 |
2 |
90 |
--------------------------------------------------------------------------------