Schedule a CloudFlow workflow by using Terraform
CloudFlow scheduling starts a workflow on a time-based trigger and is implemented based on EventBridge. CloudFlow provides no API for scheduling, so Terraform cannot create a CloudFlow schedule directly. Use Terraform to create the EventBridge resources that CloudFlow scheduling is built on.
Terraform is an open source tool that you can use to preview, configure, and manage cloud infrastructure and resources. Because CloudFlow scheduling is currently available only in the console, you have two paths to a scheduled workflow:
CloudFlow console — Configure scheduling for the workflow directly in the CloudFlow console.
Terraform — Create the EventBridge resources that CloudFlow scheduling is implemented on, and manage them as code together with the rest of your infrastructure. This topic describes this path.
The sample code in this topic supports one-click deployment. Run in one click.
Prerequisites
Use a Resource Access Management (RAM) user and create an AccessKey pair for the RAM user. An Alibaba Cloud account has all permissions on its resources, and leaked account credentials expose you to significant risks. For more information, see Create a RAM user and Create an AccessKey.
Grant the
AliyunFnFFullAccesspermission to the RAM user to manage CloudFlow (FNF) resources. For more information, see Manage RAM user permissions.Prepare a Terraform runtime environment. Use one of the following options:
(Recommended) Use Terraform in Terraform Explorer: Alibaba Cloud provides an online runtime environment for Terraform. You do not need to install Terraform. After you log on, you can use and try out Terraform online. This method is suitable for scenarios in which you want to try out and debug Terraform quickly and conveniently at no cost.
Create resources with Terraform: Terraform components are preinstalled in Alibaba Cloud Cloud Shell and the identity credentials are configured. You can run Terraform commands directly in Cloud Shell. This method is suitable for scenarios in which you want to access and use Terraform quickly and conveniently at a low cost.
Install and configure Terraform on your on-premises machine: This method is suitable for scenarios in which the network connectivity is poor or you need a custom development environment.
Use Terraform v0.12.28 or later. To check the version that is installed, run the terraform --version command.
The sample code creates CloudFlow, RAM, Simple Message Queue (formerly MNS), and EventBridge resources. Make sure that the identity you run Terraform with can create every resource type that the Resources used section lists.
Resources used
alicloud_ram_policy: Creates a RAM policy.
alicloud_ram_role: Creates a role.
alicloud_ram_role_policy_attachment: Creates a RAM role policy attachment.
alicloud_mns_queue: Creates a Simple Message Queue (formerly MNS) resource.
alicloud_event_bridge_event_bus: Creates an event bus.
alicloud_event_bridge_event_source: Creates an event source resource.
alicloud_event_bridge_rule: Creates an event rule.
random_integer: Generates the random suffix that is appended to the RAM policy name and the Simple Message Queue queue name.
Create the scheduling resources with Terraform
Create a working directory and create a configuration file named
main.tfin it.main.tfis the main Terraform file. It defines the resources to be deployed.The
regionvariable sets the region for all resources in the configuration. The sample usescn-hangzhouas the default value, so change the default value to the region that you use.variable "region" { default = "cn-hangzhou" } provider "alicloud" { region = var.region } # Define the name variable. variable "name" { default = "test-mns" } # Define the policy name variable. variable "policy_name" { type = string description = "The name of the policy." default = "test-policy" } # Define the role name variable. variable "role_name" { type = string description = "The role for eb to start execution of flow." default = "eb-to-fnf-role" } # Define the CloudFlow name variable. variable "flow_name" { type = string description = "The name of the flow." default = "test-flow" } # Define the description of the flow. variable "flow_description" { default = "For flow_description" } # Define the event bus name variable. variable "event_bus_name" { type = string description = "The name of the event bus." default = "test-eventbus1" } # Define the event bus description variable. variable "event_bus_description" { default = "For event_bus_description" } # Define the code name variable of the event source. variable "event_source_name" { type = string description = "The name of the event source." default = "test-eventsource1" } # Define the name of the event rule. variable "event_rule_name" { type = string description = "The name of the event rule." default = "test-eventrule1" } # The custom ID of the event target. variable "target_id" { type = string description = "The ID of the target." default = "test-target1" } # Obtain the UID of the current Alibaba Cloud account. data "alicloud_account" "current" { } # Create a random number. resource "random_integer" "default" { min = 10000 max = 99999 } # Create a RAM policy to define permissions. resource "alicloud_ram_policy" "policy_example" { # The name of the RAM policy. policy_name = "${var.policy_name}-${random_integer.default.result}" # (Optional) This parameter is used for resource destruction. Default value: false. force = true # The document of the RAM policy. policy_document = <<EOF { "Statement": [ { "Action": [ "fnf:*", "mns:*", "eventbridge:*", "ram:*" ], "Effect": "Allow", "Resource": [ "*" ] } ], "Version": "1" } EOF } # Create a RAM role. resource "alicloud_ram_role" "role_example" { # The name of the role. name = var.role_name # (Optional) This parameter is used for resource destruction. Default value: false. force = true # The policy document of the role. document = <<EOF { "Statement": [ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "Service": [ "fnf.aliyuncs.com" ] } } ], "Version": "1" } EOF } # Attach the created RAM policy to the RAM role to grant the corresponding permissions to the role. resource "alicloud_ram_role_policy_attachment" "attach_example" { # The name of the RAM policy. policy_name = alicloud_ram_policy.policy_example.policy_name # The type of the RAM policy. policy_type = alicloud_ram_policy.policy_example.type # The name of the RAM role. role_name = alicloud_ram_role.role_example.name } # Create a CloudFlow resource. resource "alicloud_fnf_flow" "flow_example" { depends_on = [alicloud_ram_role_policy_attachment.attach_example] # (Required) The definition of the flow. The definition must conform to the Flow Definition Language (FDL) syntax. definition = <<EOF Type: StateMachine Name: ${var.flow_name} SpecVersion: v1 StartAt: Hello World States: - Type: Pass Name: Hello World End: true EOF # The ARN of the specified RAM role that CloudFlow uses to execute the flow. role_arn = alicloud_ram_role.role_example.arn # The description of the flow. description = var.flow_description # The name of the flow. name = var.flow_name # The type of the flow. Valid values: FDL and DEFAULT. type = "FDL" } # Create an event bus to receive and route events. resource "alicloud_event_bridge_event_bus" "eventbus_example" { # The name of the event bus. event_bus_name = var.event_bus_name # (Optional) The description of the event bus. description = var.event_bus_description } # Create a Simple Message Queue (formerly MNS) queue. resource "alicloud_mns_queue" "example" { # The name. name = "${var.name}-${random_integer.default.result}" # This property defines the delay, in seconds, before a message sent to the queue can be dequeued. delay_seconds = 0 # This property specifies the maximum size, in bytes, of a message body sent to the queue. maximum_message_size = 65536 # This property defines the retention period, in seconds, of each message in the queue. message_retention_period = 345600 # The visibility timeout property of the queue. visibility_timeout = 30 # The long polling time, in seconds. polling_wait_seconds = 0 } # Create an event source and link it to the Simple Message Queue (formerly MNS) queue. resource "alicloud_event_bridge_event_source" "eventsource_example" { # The name of the event bus. event_bus_name = alicloud_event_bridge_event_bus.eventbus_example.event_bus_name # The code name of the event source. event_source_name = var.event_source_name # (Optional, Computed) Specifies whether to connect to an external data source. Default value: false. linked_external_source = true # (Optional) The type of the external data source. Valid values: RabbitMQ, RocketMQ, and MNS. Note: This field is valid only when linked_external_source is set to true. external_source_type = "MNS" # (Optional, Map) The configuration of the external source. external_source_config = { QueueName = alicloud_mns_queue.example.name } } # Define a local variable to store the ARN of the CloudFlow workflow. locals { flow_arn = format("acs:fnf:::flow/%s", var.flow_name) } # Create an event rule to match the events generated by the event source and route the events to the specified CloudFlow workflow. resource "alicloud_event_bridge_rule" "eventrule_example" { # The name of the event bus. event_bus_name = alicloud_event_bridge_event_bus.eventbus_example.event_bus_name # The name of the event rule. rule_name = var.event_rule_name # The pattern that matches the events of interest. The event pattern is in JSON format. The values are described as follows: stringEqual pattern and stringExpression pattern. filter_pattern = format("{\"source\":[\"%s\"]}", var.event_source_name) # The targets of the rule. targets { # The custom ID of the event target. target_id = var.target_id # The endpoint of the event target. endpoint = local.flow_arn # The type of the event target. type = "acs.fnf" param_list { resource_key = "Input" form = "ORIGINAL" } param_list { form = "CONSTANT" resource_key = "FlowName" value = var.flow_name } param_list { form = "CONSTANT" resource_key = "RoleName" value = var.role_name } } }Run the following command to initialize the Terraform runtime environment:
terraform initInitializing the backend... Initializing provider plugins... - Finding latest version of hashicorp/alicloud... - Installing hashicorp/alicloud v1.234.0... - Installed hashicorp/alicloud v1.234.0 (signed by HashiCorp) Terraform has created a lock file .terraform.lock.hcl to record the provider selections it made above. Include this file in your version control repository so that Terraform can guarantee to make the same selections by default when you run "terraform init" in the future. Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.Run the following command to create an execution plan and preview the changes:
terraform planRun the following command to create the CloudFlow schedule:
terraform applyyesas prompted and press Enter. Wait until the command is complete. The following output indicates that the CloudFlow schedule is created:Plan: 9 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes random_integer.default: Creating... random_integer.default: Creation complete after 0s [id=10***] alicloud_ram_policy.policy_example: Creating... alicloud_ram_role.role_example: Creating... alicloud_mns_queue.example: Creating... alicloud_event_bridge_event_bus.eventbus_example: Creating... alicloud_mns_queue.example: Creation complete after 0s [id=test-mns-10***] alicloud_ram_policy.policy_example: Creation complete after 1s [id=test-policy-10***] alicloud_ram_role.role_example: Creation complete after 1s [id=eb-to-fnf-r***] alicloud_ram_role_policy_attachment.attach_example: Creating... alicloud_ram_role_policy_attachment.attach_example: Creation complete after 0s [id=role:test-policy-10***:Custom:eb-to-f***] alicloud_fnf_flow.flow_example: Creating... alicloud_fnf_flow.flow_example: Creation complete after 0s [id=test-f***] alicloud_event_bridge_event_bus.eventbus_example: Creation complete after 2s [id=test-event***] alicloud_event_bridge_rule.eventrule_example: Creating... alicloud_event_bridge_event_source.eventsource_example: Creating... alicloud_event_bridge_event_source.eventsource_example: Creation complete after 0s [id=test-eventsour***] alicloud_event_bridge_rule.eventrule_example: Creation complete after 0s [id=test-eventbus1:test-event***] Apply complete! Resources: 9 added, 0 changed, 0 destroyed.random_integerresource generates the numeric suffix in the resource names and IDs, so these values differ each time you deploy the configuration.
Verify the results
Verify the resources that Terraform created in either of the following ways.
Run the terraform show command
Run the following command to query the details of the resources that Terraform created:
terraform showshell@Alicloud:~/ens/fnf02$ terraform show
# alicloud_event_bridge_event_bus.eventbus_example:
resource "alicloud_event_bridge_event_bus" "eventbus_example" {
description = "For event_bus_description"
event_bus_name = "test-eventbus1"
id = "xxx"
}
# alicloud_event_bridge_event_source.eventsource_example:
resource "alicloud_event_bridge_event_source" "eventsource_example" {
event_bus_name = "test-eventbus1"
event_source_name = "test-eventsource1"
external_source_config = {
"QueueName" = "test-mns-10***"
}
external_source_type = "MNS"
id = "test-eventsource1"
linked_external_source = true
}
# alicloud_event_bridge_rule.eventrule_example:
resource "alicloud_event_bridge_rule" "eventrule_example" {
event_bus_name = "test-eventbus1"
filter_pattern = jsonencode(
{
source = [
"test-eventsource1",
]
}
)
id = "xxx"
rule_name = "test-eventrule1"
status = "ENABLE"
targets {
endpoint = "xxx"
push_retry_strategy = "BACKOFF_RETRY"
target_id = "test-target1"
type = "acs.fnf"
param_list {
form = "CONSTANT"
resource_key = "FlowName"
}
}
}Log on to the CloudFlow console
After the resources are created, log on to the CloudFlow console to check whether the workflow is created as expected.
Log on to the CloudFlow console.
Go to the Workflows page.
Find the workflow that Terraform created and check its properties.
The sample configuration creates a workflow with the following properties. If you changed the variable defaults, check the workflow against your own values.
Workflow name —
test-flow, the default value of theflow_namevariable.Type —
FDL, the value of thetypeattribute of thealicloud_fnf_flowresource.Description —
For flow_description, the default value of theflow_descriptionvariable.
Clean up resources
When you no longer need the resources that you created or manage by using Terraform, run the following command to release the resources.
terraform destroy releases every resource that this configuration created, including the CloudFlow workflow, the RAM policy, the RAM role, the Simple Message Queue queue, and the EventBridge event bus, event source, and event rule.
terraform destroyFor more information about terraform destroy, see Common Terraform commands.
Complete example
The following configuration is the same one that the procedure builds step by step, provided as a single block that you can copy in full. Run in one click.
Troubleshooting
If terraform init times out due to reasons such as network latency and you cannot download the provider as expected, see Configure an acceleration solution for Terraform Init.