Using Custom Actions

Not Oracle Cloud at Customer This topic does not apply to Oracle Cloud at Customer.

Edit your Oracle Cloud Stack template file and use Software Components to execute custom operating system (OS) commands or scripts after a stack resource is provisioned.

For example, you can use custom actions to:

  • Install an OS package

  • Modify the default OS configuration

  • Create a database schema

  • Deploy an application

  • Download files from cloud storage

Custom actions are only supported for cloud resources that provide a Secure Shell (SSH) interface to their administration node (virtual machine). The specified OS commands are run on the administration node after the resource is created. If a resource consists of multiple administration nodes, the commands are run only from the first node.

Note:

Custom actions are not supported on Oracle-managed or Autonomous cloud services.

Tutorial icon Tutorials are also available to help you create custom actions.

Basic Syntax

Add a resource of type SoftwareComponent to the template. Within the parameters node of this resource, add a sequence named configs.

resources:
  ...
  resource_name:
    type: SoftwareComponent
    parameters:
      configs:
        - configuration
        - configuration

Each object in the configs sequence describes a custom action. Specify one or more Bash OS commands to run on the target cloud resources.

parameters:
  configs:
    - actions: [CREATE]
      name: configuration_name
      config:
        Fn::Base64:
          bash_commands
      runAsUser: OS_user
      timeout: minutes
      continueOnFailure: true_or_false

The available attributes for a custom action are:

  • actions – The only supported value is [CREATE]. All custom actions run after the target cloud resource is created.

  • name – An optional name for this custom action.

  • config – One or more Bash commands as a Base64 encoded string. Separate multiple commands with new line (\n) characters.

  • runAsUser – The OS user name against which to run the commands. The default user is opc.

  • timeout – The number of minutes within which the custom action is expected to complete. If the action does not complete within this time, stack creation fails. The default value is 5 minutes.

  • continueOnFailure – If false, the creation of the stack fails if this custom action fails. If true, a warning is added to the activity log, but the creation of the stack continues.

You can also use the Join function as a convenient method of defining an action with multiple commands:

name: configuration_name
config:
  Fn::Base64:
    Fn::Join:
      - "\n"
      -
        - bash_command
        - bash_command

Below is an example Software Component resource that defines a custom action:

resources: 
  updateDatabaseOS:
    type: SoftwareComponent
    parameters:
      configs:
        - actions: [CREATE]
          name: updateHosts
          config:
            Fn::Base64:
              Fn::Join:
                - "\n"
                -
                  - touch ~/stack.out
                  - echo 'Updating hosts' >> ~/stack.out
                  - echo 'myhost 192.168.1.10' >> /etc/hosts
          continueOnFailure: true

Tip:

When using the Join function, be sure that all members of the same sequence have the same indentation. The following example is invalid:
Fn::Join:
  - "\n"
  -
  - This is 
  - not valid

Assigning a Custom Action to a Resource

After defining Software Components in your template, you refer to them within the definitions of other cloud resources in the same template. Add a configs sequence within the resource, and place it after the parameters node. The configs sequence lists the names of the Software Component resources that Oracle Cloud Stack will execute after this resource is successfully created.

Use the GetResource function to retrieve each Software Component, and also give each a logical configuration name.

resources:
  ...
  resource_name:
    type: resource_type
    parameters:
      ...
    configs:
      - name: configuration_name
        config: { "Fn::GetResource": software_component_name }
      - name: configuration_name
        config: { "Fn::GetResource": software_component_name }

For example:

HRDatabase:
  type: dbaas
  parameters:
    ...
  configs:
    - name: HRDatabaseUpdateOS
      config: { "Fn::GetResource": updateDatabaseOS }

Inputs and Environment Variables

The use of template functions, such as GetParam, is not supported within the OS commands of a custom action. However, you can parameterize the actions in a template by using environment variables in your OS commands. Add a sequence named inputs within the parameters node of your Software Component resource, and then declare the environment variables that are used in this custom action.

resources:
  ...
  resource_name:
    type: SoftwareComponent
    parameters:
      configs:
        ...
      inputs:
        - name: env_variable
        - name: env_variable 

Refer to these environment variables in the OS commands of the Software Component. For example:

resources: 
  updateDatabaseOS:
    type: SoftwareComponent
    parameters:
      configs:
        - actions: [CREATE]
          name: updateHosts
          config:
            Fn::Base64:
              Fn::Join:
                - "\n"
                -
                  - echo 'Updating database OS...'
                  - echo "myhost ${storage_address}" >> /etc/hosts
      inputs:
        - name: storage_address

When you assign the Software Component to another cloud resource using the configs sequence, you must specify the values for any input parameters by adding an object named params to the sequence.

resources:
  ...
  HRDatabase:
    type: dbaas
    parameters:
      ...
    configs:
      - name: configuration_name
        config: { "Fn::GetResource": software_component_name }
        params:
          input_name: value
          input_name: value
      - name: configuration_name
        config: { "Fn::GetResource": software_component_name }
        params:
          input_name: value
          input_name: value

You can use template functions when specifying an input’s value, such as GetParam and GetAtt. For example:

configs:
  - name: HRDatabaseUpdateOS
    config: { "Fn::GetResource": updateDatabaseOS }
    params:
      log_file: stack.out
      storage_address: { "Fn::GetParam": storageIPAddress }

Downloading Files

In your custom actions, you can use wget, curl, or similar OS commands to download scripts and other files to the administration node in the target cloud resource. For example, you could download and extract an archive file found in an Oracle Cloud Infrastructure Object Storage container, and then execute one or more scripts found in the archive.

Activity Log

You can verify the execution of your custom actions by viewing the activity log for a cloud stack. The log messages specify the name of the target resource, the name of the action that was executed, and the node on which it was executed.

[stack_name] : Attempting to execute SoftwareComponent script - [identity_domain/resource_name] : [action_name] on host [node_ip_address]
...
[stack_name] : Execution completed successfully. SoftwareComponent - [identity_domain/resource_name] : [action_name] on host [node_ip_address]

For example:

[MyStack] : Execution completed successfully. SoftwareComponent - [MyIdentityDomain/HRDatabase] : [updateHosts] on host [192.168.10.10]

See Viewing the Details of a Cloud Stack.

Best Practices

  • Program a custom action so that it can run multiple times without failing or behaving unexpectedly (idempotent). A custom action might be run more than once in the following scenarios:

    • Oracle Cloud Stack retries the execution of a custom action after a communication failure with the target resource.

    • If you create a cloud stack with the RETAIN option, and then resume the stack after a resource provisioning failure, Oracle Cloud Stack also (re)executes any custom actions that are associated with the failed resource.

  • In a custom action, return 0 to indicate success and return 1 to indicate a failure.

  • By default, all existing resources are terminated if there is a failure during the creation of a stack, which includes the deletion of any log files generated by a custom action. To facilitate troubleshooting, record log messages to an external location like cloud storage.