In the previous blog, we discussed calling an Oracle Function from VB. In this post, we accomplish the same task using the OCI API Gateway acting as a point of entry to the Function. The API Gateway provides a single point of entry to the services in your organization, and helps in consolidating common tasks such as request/response transformations, CORS support, request limiting etc
We will build upon resources used in the previous blog so you are recommended to complete that before you proceed.
We will use a python based OCI function from the sample OCI functions in github. This Function lists the compartments available in the tenancy. Since this function also calls other OCI Resources (ListCompartments), we will need to place this Function in a Dynamic Group. This would be an addition to what we did in the hello-java function in the previous blog
Repeat the section of Create the hello-java function in the previous blog with the following differences:
wget https://raw.githubusercontent.com/oracle/oracle-functions-samples/master/samples/oci-list-compartments-python/func.py
wget https://raw.githubusercontent.com/oracle/oracle-functions-samples/master/samples/oci-list-compartments-python/func.yaml
wget https://raw.githubusercontent.com/oracle/oracle-functions-samples/master/samples/oci-list-compartments-python/requirements.txt
When you invoke the function using fn invoke, you would get an error as below
Error invoking function. status: 502 message: function failed.
This is because our Function is now calling OCI Resources. We will add the necessary configuration in the next section in order for the Function to be able to access other resources.
For the Function to be able to access OCI Resources, we need to make sure it is within a Dynamic Group.
Navigate to Dynamic Groups from Identity -> Dynamic Groups or via quick search, and begin creating a Dynamic Group. Give a relevant name (e.g. FunctionsInVBAPP). Add a rule expression that will select all the relevant functions and click Create. In my case, I have selected all functions that belong to the oci-fn-vb compartment with the below rule
ALL {resource.type = 'fnfunc', resource.compartment.id = ' ocid1.compartment.oc1..aaaaaaaaxyz'}
where the resource.compartment.id has the OCID of the oci-fn-vb compartment
Note : The ListCompartments API doesnt require a special Policy to gain access. But for other kinds of actions, like ListVCNs, you might have to add an IAM Policy that will give this group access to the relevant API (see the help documentation for more on this)
Once you have created the Dynamic Group for the Function, try to invoke the function again from CloudShell - this should now return a list of compartments
fn invoke oci-fn-vb-app oci-list-compartments-python
{"compartments": [["ocid1.compartment.oc1..aaaaaaaaf...abc", "firstcompartment"], ["ocid1.compartment.oc1..aaaaaaaaf...def", "ManagedCompartmentForPaaS"], ["ocid1.compartment.oc1..aaaaaaaao...efa", "oci-fn-vb"], ["ocid1.compartment.oc1..aaaaaaaaf...ghi", "oci-test"]]}
Let us now create and configure an API Gateway to connect to the Function
Navigate to Developer Services -> API Gateway. Select the oci-fn-vb Compartment, and start creating a Public API Gateway. Select the VCN and public subnet that was created in the previous blog. This has the necessary routing to the Internet Gateway too.
After the API Gateway is created, we need to configure a backend that would route to our Function oci-list-compartments-python. We add backends and routes via Deployments. Click on the newly created API Gateway oci-fn-vb-apigw, navigate to Deployments and click on Create Deployments. Choose the "From Scratch" option and enter a relevant name and /v1 as the path prefix. For now we wont configure any authentication or CORS, so leave the other options as-is.
Click Next and configure the Route. Give the following details :
Path : /compartment
Methods : GET
Type : Oracle Functions
Application : oci-fn-vb-app
Function : oci-list-compartments-python
Click Next and review the information provided and create the deployment. After creation, note down the endpoint for the Deployments. The format would be something like below:
https://plbo2fabcigu.apigateway.ap-mumbai-1.oci.customer-oci.com/v1
Therefore full URL to the compartment resource would be
https://plbo2fabcigu.apigateway.ap-mumbai-1.oci.customer-oci.com/v1/compartment
If you try to connect to the compartment Resouce URL that we got in the previous section via browser or any API client like Postman, it is likely that you will get a timeout. This is because the public subnet is not accepting HTTPS traffic.
Since we had created the VCN via the VCN Wizard, we already have the route tables and Internet Gateway correctly configured. There is one more step we need to complete for the subnet to accept HTTPS traffic, which is defining an HTTPS ingress rule for our subnet.
Navigate to Networking -> Virtual Cloud Networks and select the VCN (In my case, it is oci-fn-vb-VCN)
Click on the VCN, this should show both the public and private subnets.
Click on the public subnet. This should show you the Security Lists of the public subnet.
Clicking on the security list would show you all the Ingress Rules. Proceed to add an Ingress Rule for HTTPS as below
Description : HTTPS ingress rule
Source CIDR : 0.0.0.0/0
IP Protocol : TCP
Source Port Range : All (Default)
Destination Port Range : 443
If now you try to connect to the resource URL, it should be connectable now, but it will likely give an error like below : {"message":"Internal Server Error","code":500}
This requires the API Gateway be configured with adequate permissions to call the required Function, which we will see in the next section
Go to Identity -> Policies. Create a Policy that allows API Gateway to execute all Functions in the oci-fn-vb compartment
E.g.
ALLOW any-user to use functions-family in compartment
where
ALL { request.principal.type= 'ApiGateway' ,
request.resource.compartment.id = ''
}
Now connecting to resource URL https://plbo2fabcigu.apigateway.ap-mumbai-1.oci.customer-oci.com/v1/compartment
will work and give you the list of compartments
{"compartments": [["ocid1.compartment.oc1..aaaaaaaaf...abc", "firstcompartment"], ["ocid1.compartment.oc1..aaaaaaaaf...def", "ManagedCompartmentForPaaS"], ["ocid1.compartment.oc1..aaaaaaaao...efa", "oci-fn-vb"], ["ocid1.compartment.oc1..aaaaaaaaf...ghi", "oci-test"]]}
Login to Visual Builder. Create a Visual Application OCIServiceTest. In this, navigate to Service Connections and proceed to create a new Service Connection. Choose the Define by Endpoint category when prompted to select Source
In the Service Connection Wizard, choose as below :
Method : GET
URL : API Gateway Deployment Endpoint full path ( e.g. https://plbo2fabcigu.apigateway.ap-mumbai-1.oci.customer-oci.com/v1/compartment)
Action Hint : Get Many
Click Next. Choose a relevant Service name and title. In my case the service is called ociCompartments.
Navigate to the Servers tab. Since we have not specified any authentication to the API Gateway deployment, we can choose to have no authentication. However since we also didnt configure any CORS support, we would need to set Connection Type as "Dynamic doesnt support CORS" (More on Connection Types here )
Next, navigate to the Test tab and test the Service Connection. It should give you a status code of 200 OK and a valid response
Finally create the Service Connection. Now this can be added to web and mobile apps for retrieving data.
We covered the aspects of connecting to a Function exposed via the API Gateway. There are still some improvements that can be made, namely Authentication and CORS support. We will see how to tackle this in the next blog