Note:

Use Oracle Cloud Infrastructure DevOps to Automate OCI Resource Manager Deployments

Introduction

Oracle Cloud Infrastructure (OCI) Resource Manager is a fully managed service that helps teams manage and automate their Infrastructure as Code (IaC). It lets teams collaborate over the Terraform configuration, define permissions on various actions, provides state locking to prevent corruption, automatically stores all state files in persistent storage and takes care of configuring the Terraform provider. For the delivery and deployment of all software, not just Terraform, there is OCI DevOps, an end-to-end, continuous integration/continuous delivery (CI/CD) platform for developers with private code repositories, triggers, build and deploy pipelines, and more.

OCI Resource Manager has built in automation for Terraform and integrations with multiple source code control systems to achieve basic CI/CD. In this tutorial, we will look at how we can use OCI DevOps to expand upon these CI/CD capabilities by automatically redeploying OCI Resource Manager stacks on Terraform code changes.

The Flow

Flow diagram

The process starts with a user pushing a new Terraform configuration to the code repository, which triggers the build and deployment pipelines. This results in the creation of a shell environment that uses the OCI Command Line Interface (CLI) to apply the OCI Resource Manager stack with the new configuration.

Objectives

Task 1: Set up OCI DevOps Code Repository

  1. Log in to the OCI Console, navigate to Developer Services, DevOps, Projects and create a DevOps project which will hold all of the resources in your CI/CD workflow.

  2. Create a Code Repository and upload your Terraform configuration. There are plenty of Oracle-provided templates you can use. In this tutorial, the Terraform simply changes the description of an OCI Notifications topic.

    resource "oci_ons_notification_topic" "test_notification_topic" {
        #Required
        compartment_id = <compartment_id>
        name = "RM_DevOps_Automation_Tutorial"
    
        #Optional
        description = "This is a test notification topic."
    }
    

    Initial Notification configuration

Task 2: Create a Shell Artifact

We need to create the artifact used in the deployment pipeline first. As we will be executing a shell script to run the OCI CLI, create an artifact of type Command specification. In this tutorial, we will use Artifact source to be Inline with the following commands:

version: 0.1
component: command
timeoutInSeconds: 1200
steps:
 - type: Command
   timeoutinSeconds: 900
   name: Invoke RMS
   command: |
     echo "Running RM apply command"

Create shell artifact

For more information about the syntax and additional parameters, see Command Specification documentation. We will add more details to this script later.

Task 3: Create a Deployment Pipeline

Deployment pipelines are used to deploy artifacts.

  1. Create a deployment pipeline and a stage of type Shell.

    Create shell stage

  2. Click Select artifact and select the artifact created in Task 2. Select the Shape and Network configuration that satisfies your requirements.

    Select artifact

    Note: Policies: When creating stages, a list of recommended policies will be linked, make sure to add them. In addition, our deployment pipeline will be interacting with OCI Resource Manager and OCI Notifications, so make sure to give your dynamic group access to ons-topics, orm-stacks and orm-jobs. For more information about a complete list of permissions for each service, see Policy Reference.

Task 4: Create a Build Pipeline

Even though we will not be building any artifacts, we still need a build pipeline to trigger our deployment pipeline.

  1. Create a build pipeline and a stage of type Trigger deployment.

    Create build stage

  2. Click Select deployment pipeline and select the pipeline you created in Task 3.

    Select deployment pipeline

Task 5: Create a Trigger

We need to create a trigger that invokes on code pushes.

  1. Navigate to Triggers and click Create trigger.

  2. In the Create trigger page, enter the following information.

    • Source Connection: Enter OCI code repository.
    • Select code repository: Select repository created in Task 1.
  3. Click Add action and enter the following information.

    • Build pipeline: Select the build pipeline created in Task 4.
    • Event: Select Push.
    • Build run conditions: Enter according to your use case. In this example, we will enter the following information.
      • Source branch: Enter main.
      • Files to include: Enter main.tf.

    Create trigger

Task 6: Test the Flow

Here is the workflow that we have followed up to this point in the tutorial.

  1. Code push.
  2. Trigger.
  3. Build pipeline.
  4. Deployment pipeline.
  5. Shell script runs echo "Running RM apply command".

Confirm the working of the workflow before adding more complexity to the shell script.

  1. Push new code.

    Push code

  2. Confirm build pipeline triggered.

    Build in progress

  3. Confirm deployment pipeline triggered.

    Deployment in progress

  4. Confirm shell script runs successfully

    Test flow success

Everything is working as expected. The last task is to refashion our shell script to trigger the Resource Manager stack.

Task 7: Modify Shell Script to Trigger Resource Manager Stack

The Shell stage container image runtime includes shell interpreters, shell utilities, CLIs, and many more tools. For more information, see Shell Container Image Runtime Details.

We will leverage the OCI CLI to invoke Resource Manager. Our shell script currently looks like this:

version: 0.1
component: command
timeoutInSeconds: 1200
steps:
 - type: Command
   timeoutinSeconds: 900
   name: Invoke RMS
   command: |
     echo "Running RM apply command"

To modify the shell script, follow the steps:

  1. Create a job.

    The first call we will make is create-apply-job. This creates an apply job on our Resource Manager stack. We will also save the job_id of the job as a variable to reference the job in the next step.

    job_id=$(oci resource-manager job create-apply-job --stack-id <Stack OCID> --execution-plan-strategy AUTO_APPROVED --wait-for-state SUCCEEDED --wait-for-state FAILED --query data.id --raw-output)
    

    For more information, see OCI CLI Command Reference: create-apply-job.

  2. Get the job status.

    We need to check if the job succeeded or failed. To do that, we will pass the job_id into job get, which returns the job’s properties. Specifically, we care about the lifecycle-state.

    job_state=$(oci resource-manager job get --job-id $job_id --raw-output --query 'data."lifecycle-state"')
    

    For more information, see OCI CLI Command Reference: job get.

  3. Analyze the job status.

    Add logic to change the exit code depending on whether the job succeeded (0) or failed (1).

    if [ $job_state == SUCCEEDED ]; then
      echo "Resource Manager job succeeded"
      exit 0
    else
      echo "Resource Manager job failed"
      exit 1
    fi
    
  4. After aggregating the previous steps and adding some additional print statements, your shell script should look something like this:

    version: 0.1
    component: command
    timeoutInSeconds: 1200
    steps:
    - type: Command
      timeoutinSeconds: 900
      name: Invoke RMS
      command: |
        echo "Running RM apply command"
        job_id=$(oci resource-manager job create-apply-job --stack-id ocid1.ormstack.oc1.iad.amaaaaaann2vciya6arauok6db5epqnhlfdmbf5ee7td6gydzwvarzanaxyq --execution-plan-strategy AUTO_APPROVED --wait-for-state SUCCEEDED --wait-for-state FAILED --query data.id --raw-output)
        echo "RMS plan job id is:"
        echo $job_id
        job_state=$(oci resource-manager job get --job-id $job_id --raw-output --query 'data."lifecycle-state"')
        echo "Apply job lifecycle-state is:"
        echo $job_state
        if [ $job_state == SUCCEEDED ]; then
          echo "Resource Manager job succeeded"
          exit 0
        else
          echo "Resource Manager job failed"
          exit 1
        fi
    

Note: This is a simple example showing basic functionality. You can customize the script to your requirement.

Task 8: End-to-End Test

Your full architecture and flow should look like this:

Flow diagram

Confirm the working of the architecture.

  1. Push new code.

    Push code

  2. Confirm shell script runs successfully.

    Shell success

  3. Confirm Terraform is applied successfully.

    Notification topic updated

Next Steps

This tutorial showed how to automate OCI Resource Manager stack deployments with OCI DevOps. This is a simple example showing the basic flow. You are encouraged to take the concepts learned and build upon them, tailor them to your use case, and incorporate them into your existing CI/CD pipelines.

Acknowledgments

More Learning Resources

Explore other labs on docs.oracle.com/learn or access more free learning content on the Oracle Learning YouTube channel. Additionally, visit education.oracle.com/learning-explorer to become an Oracle Learning Explorer.

For product documentation, visit Oracle Help Center.