Serverless is a cloud-native development model that allows developers to build and run applications without having to manage servers. Oracle Cloud Functions is a serverless platform that lets developers create, run, and scale applications without managing any infrastructure.
In the current use case, we will explore how we can use Oracle Cloud Functions as backend in the API Gateway so that they can be consumed by any web based applications to build the serverless applications.
The following OCI components are used in the current usecase
We have a static web page based on plain html with all required javascript/css embedded inside it. This page contains the UI to handle a generic product store which contains various products and their availability(count of available items for each product). The UI contains the following operations
- Fetch all products
- Add a new product to the store
- Update count of an existing product
- Delete an existing product from the store
The product data is maintained in ATP database. When this UI is accessed using any of the above operations, it invokes the respective OCI API Gateway endpoint URL using REST call. API Gateway is responsible for invoking the Oracle function mapped to the path invoked by the application. This Oracle Function is responsible for interacting with ATP to perform all the required CRUD operations.
We need to setup the following OCI components.
- Create an Autonomous Transaction Processing (ATP) Database
- From the ATP details page, click on DB Connection -> Instance Wallet -> Download Wallet. Extract the contents to any folder. You need to refer the tnsnames.ora file in the next section
- Access the ATP Service Console. In the Home page, make a note of the ORDS base URL by clicking on Copy URL under RESTful Services and SODA section.
- Click on Database Actions to open the SQL Developer Web. Clik on SQL to open the SQL worksheet and execute the following queries
/* Create a user 'test_user' for connecting to the ATP from the application */
CREATE USER test_user IDENTIFIED BY default_Password1;
/* Grant all necessary permission for the tes_user created above */
GRANT CREATE SESSION TO test_user;
GRANT UNLIMITED TABLESPACE TO test_user;
/* Create a separate role 'test_role' and grant it to the above user */
CREATE ROLE test_role;
GRANT test_role TO test_user;
/* Create a table for storing the product information. We are storing only 2 details namely product name and product count */
CREATE TABLE test_user.products (
name VARCHAR2(20),
count NUMBER
);
/* Grant relevant permissions for the test_role created above */
GRANT SELECT, INSERT, UPDATE, DELETE ON test_user.products TO test_role;
/* Prepare some sample product data for testing the application */
INSERT INTO test_user.products VALUES ('Pen',100);
INSERT INTO test_user.products VALUES ('Pencil',200);
INSERT INTO test_user.products VALUES ('Notebook',50);
INSERT INTO test_user.products VALUES ('Sketch pen',80);
INSERT INTO test_user.products VALUES ('Eraser',150);
/* Verify the inserted product data */
select name, count from test_user.products;
- From Global Action Menu, select Administration -> Database Users. Select the TEST_USER and click on Enable REST
Vaults securely store master encryption keys and secrets to pass the sensitive information to the application. In the current usecase, we will use the Vault to create the secrets for the ATP database username and password.
- Create a Vault. Make sure that you don't click on the check box for Virutal Private Vault as this is only demo
- Go to the Vault details page and select Master Encryption Keys from the Resources. Now click on the Create Key
- Enter the required information and click on Create Key. Select the Protection mode as the Software
- Select Secrets and click on Create Secret. This secret is meant for storing the ATP database user ID. Fill the required information. For Encryption Key, select the key created in the previous step. Give test_user as the content and click Create Secret.
- Simliary create a secret for storing the ATP database password
- Make a note of the OCID for both the secrets created above.
- Upgrade to the latest fn CLI
- Setup your environment for Functions. Make sure all the setup instructions followed as mentioned
- Create an application with a name 'serverless-demo'
- Add the following configuration parameters to the application
- ORDS_BASE_URL : The URL we copied in the steps mentioned in the section on ATP Database.
- DB_USER_SECRET_OCID : The OCID of the ATP DB User ID secret created in the previous section
- DB_PASSWORD_SECRET_OCID : The OCID of the ATP DB password secret created in the previous section
- In the cloud shell, clone the github repository:
$git clone https://github.com/subhashchandrab/oci-serverless-example.git
$cd atp-client-java-function
-
Setup your environment for pushing the function image to the OCI repository. Please refer OCI Fn quickstart for help.
-
After logging in to the OCI registry, execute the following command to verify that the function application created above(serverless-demo) is listed
$fn list apps
NAME ID
serverless-demo ocid1.fnapp.oc1.phx.aaaa.....
- Deploy the function into the application
$fn -v deploy --app serverless-demo
- From OCI Console, click Developer Services -> Functions -> Application -> serverless-demo. Verify that the function named product-store-operations-java is shown in the list of functions.
- Create an API Gateway
- Create a deployment named product-store with CORS configuration as shown below
-
Click Next and create a Route for the path /getProducts as shown below. Type should be selected as Oracle Functions and the application and function should be selected by referring to the function deployed in earlier section.
-
Similar to the above step, create the following routes
PATH | METHODS | TYPE | APPLICATION | FUNCTION NAME |
---|---|---|---|---|
/addProduct | POST | Oracle Functions | serverless-demo | product-store-operations |
/updateProduct | POST | Oracle Functions | serverless-demo | product-store-operations |
/deleteProduct | POST | Oracle Functions | serverless-demo | product-store-operations |
-
Click Next and click Create
-
Setup the IAM policy for API GW to use OCI functions
ALLOW any-user to use functions-family in compartment <compartment-name> where ALL {request.principal.type= 'ApiGateway', request.resource.compartment.id = 'ocid1.compartment.oc1.....'}
- API Gateway communicates on port 443, which is not open by default. You have to add a new stateful ingress rule for the regional subnet in which the API Gateway is located to allow traffic on port 443. VCN -> Subnet -> Default Security List -> Add Ingress Rule and add the rule as shown below
Source Type: CIDR
Source CIDR: 0.0.0.0/0
IP Protocol: TCP
Source Port Range: All
Destination Port Range: 443
- Go to the git cloned repository above.
$cd front-end/html
$vi index.html
- Locate the following line and update the apiEndpointUrl with the URL copied in the previous section(from API Gateway Deployment Details page)
var apiEndpointUrl = "https://*******.apigateway.*****.oci.customer-oci.com";//Replace the API Gateway endpoint URL here
- Save the file
- Create a standard type object storage bucket with all default settings
- Upload the index.html(Updated index.html from previous section) file into the bucket.
- Create a Pre-Authenticated Request for the uploaded file and note down the URL
- Go to the Deployment Details page for the API deployment created earlier. Add the following route and update the URL with the URL copied in the previous step
- Copy the API Gateway deployment endpoint URL and paste it in a browser. You should see the following operations. Perform the operations like Add Product, Delete Product and Update Product
We verified how we can build serverless applications on OCI using the API Gateway, Oracle Functions and ATP database.