Automating IT Operations with Oracle Functions

March 16, 2020 | 4 minute read
Raghavendra Prasad
Solutions Architect, Product Management
Text Size 100%:

Oracle Functions is a fully managed, multi-tenant, highly scalable, functions-as-a-service platform. It’s built on enterprise-grade Oracle Cloud Infrastructure components and powered by the open source Fn Project serverless platform. Along with Oracle Events, Oracle Functions can deliver powerful capabilities for infrastructure and application automation. Together, they enable services to act automatically based on state changes in infrastructure resources, a common use case for enterprise IT environments.

This post walks through an example of a function that verifies whether a compute instance is tagged correctly when it’s provisioned. If the instance isn’t tagged properly, the function acts to stop the instance. This practice is common in infrastructure automation; it allows resources to be audited for compliance with internal governance policies as they are created, rather than after.

This function is triggered by the Instance - Launch End event, which the Compute service generates at the completion of instance provisioning, based on whether the instance succeeds or fails.

This example uses Oracle Cloud Infrastructure Search to search for Compute resources with a tag key of costcenter and tag value of 1234.

Diagram that shows the process flow of compute provisioning triggering an event, which can trigger a function to stop the instance if it does not comply with security policies.

Prerequisites

  • Set up your tenancy for Functions development.

  • Set up the Fn CLI with Oracle Functions.

  • To use and retrieve information about other Oracle Cloud Infrastructure services, include the function in a dynamic group. The following example rule allows functions in a specific compartment to be included in a dynamic group:

    Copied to Clipboard
    Error: Could not Copy
    Copied to Clipboard
    Error: Could not Copy
    ALL {resource.type = 'fnfunc', resource.compartment.id = 'ocid1.compartment.oc1..exampleuniqueID'}

    For more information, see To create a dynamic group.

  • Create or update policies to grant dynamic group access to resources.

    After your dynamic group is created, create a policy that allows the dynamic group to use the instances in the compartment. Your policy should look something like this:

    Copied to Clipboard
    Error: Could not Copy
    Copied to Clipboard
    Error: Could not Copy
    Allow dynamic-group  to use instances in compartment

    For example:

    Copied to Clipboard
    Error: Could not Copy
    Copied to Clipboard
    Error: Could not Copy
    Allow dynamic-group demo-func-dyn-group to use instances in compartment demo-func-compartment

    For more information, see Policy Syntax.

Create an Application

Use the Oracle Cloud Infrastructure Console to create an application in Oracle Functions.

  1. From the navigation menu, select Developer Services, and then select Functions.

    Screenshot that shows the navigation menu in the Console, with Developer Services and Functions selected.

  2. Click Create Application and then enter values in the New Application dialog box. If you have previously created VCNs, they are listed, and you can select the appropriate subnet.

    Screenshot that shows the New Application dialog box.

  3. Open a terminal and create the Python function:

    Copied to Clipboard
    Error: Could not Copy
    Copied to Clipboard
    Error: Could not Copy
    fn init --runtime python stop-untagged-instance
     
    cd stop-untagged-instance
  4. In the requirements.txt file, add the following entries:

    Copied to Clipboard
    Error: Could not Copy
    Copied to Clipboard
    Error: Could not Copy
    fdk
    oci

    When the Compute service emits the Instance - Launch End event, the JSON looks as follows:

    Copied to Clipboard
    Error: Could not Copy
    Copied to Clipboard
    Error: Could not Copy
    {
      "eventType" : "com.oraclecloud.computeapi.launchinstance.end",
      "cloudEventsVersion" : "0.1",
      "eventTypeVersion" : "2.0",
      "source" : "ComputeApi",
      "eventTime" : "2020-03-04T21:24:16.151Z",
      "contentType" : "application/json",
      "data" : {
        "compartmentId" : "ocid1.compartment.oc1..exampleuniqueID",
        "compartmentName" : "sandbox",
        "resourceName" : "instance-20200304-1322",
        "resourceId" : "ocid1.instance.oc1.iad.exampleuniqueID",
        "availabilityDomain" : "QGaa:US-ASHBURN-AD-1",
        "additionalDetails" : {
          "imageId" : "ocid1.image.oc1.iad.exampleuniqueID",
          "shape" : "VM.Standard2.1",
          "type" : "CustomerVmi"
        }
      },
      "eventID" : "08a71051-cb5c-490d-8e47-2354cfe503b5",
      "extensions" : {
        "compartmentId" : "ocid1.compartment.oc1..exampleuniqueID"
      }
    }

    The resourceId is the instance identifier (OCID).

Following are some snippets of code from the func.py file:

  • From the JSON body, get the instance ID:

    Copied to Clipboard
    Error: Could not Copy
    Copied to Clipboard
    Error: Could not Copy
    body = json.loads(data.getvalue())
    instanceId = body["data"]["resourceId"]
  • Use a signer to authenticate to Oracle Cloud Infrastructure services:

    Copied to Clipboard
    Error: Could not Copy
    Copied to Clipboard
    Error: Could not Copy
    signer = oci.auth.signers.get_resource_principals_signer()
  • Use Oracle Cloud Infrastructure Search to verify whether the Compute instance is properly tagged:

    Copied to Clipboard
    Error: Could not Copy
    Copied to Clipboard
    Error: Could not Copy
    search_client = oci.resource_search.ResourceSearchClient(config={}, signer=signer)
    key="costcenter"
    value="1234"
    structured_search = oci.resource_search.models.StructuredSearchDetails(
    query="query instance resources where ((freeformTags.key != '{}' && freeformTags.value != '{}') && (identifier='{}'))".format(key,value,instanceId),
    type='Structured',
    matching_context_type=oci.resource_search.models.SearchDetails.MATCHING_CONTEXT_TYPE_NONE)
    results = search_client.search_resources(structured_search)
  • If the search finds that the instance was not tagged properly, then stop the instance:

    Copied to Clipboard
    Error: Could not Copy
    Copied to Clipboard
    Error: Could not Copy
    compute_client = oci.core.ComputeClient(config={}, signer=signer)
    try:
      if compute_client.get_instance(instanceId).data.lifecycle_state in ('RUNNING'):
      try:
          resp = compute_client.instance_action(instanceId,'STOP')
      except oci.exceptions.ServiceError as :
         print('Action failed. {0}'.format(e), flush=True)
        raise
      else:
       print('The instance {0} was in the incorrect state to stop'.format(instanceId),flush=True)
  • Deploy the function:

    Copied to Clipboard
    Error: Could not Copy
    Copied to Clipboard
    Error: Could not Copy
    fn deploy --app control-instance-app

Create an Events Rule

  1. In the navigation menu of the Console, select Application Integration, and then select Events Service.

    Screenshot that shows the navigation menu in the Console, with Application Integration and Events Service selected.

  2. Click Create Rule and enter values in the Edit Rule dialog box.

    In this example, the service name is Compute, the event type is Instance - Launch End, and the action to take is to call the stop-untagged-instance function in the control-instance-app function application.

    Screenshot that shows the Edit Rule dialog box with the specified values entered.

Test the Function

Launch a Compute instance with no tags.

Screenshot that shows an instance details page indicating that no tags are associated with the instance. The instance is in the Provisioning stage.

After a few minutes, you should see that the instance has stopped for you to take further action.

Screenshot that shows an instance details page indicating that no tags are associated with the instance. The instance is in the Stopped stage.

Conclusion

This post shows an example of how to implement IT compliance rules by using Cloud Events and Functions in Oracle Cloud Infrastructure.

Resources

Raghavendra Prasad

Solutions Architect, Product Management


Previous Post

Using Local Persistent Volumes with Container Engine for Kubernetes

Raghavendra Prasad | 3 min read

Next Post


Harnessing Artificial Intelligence Algorithms on Oracle Cloud to Reimagine Shopping

Akshai Parthasarathy | 1 min read
Oracle Chatbot
Disconnected