mirror of
https://gitea.com/mcereda/oam.git
synced 2026-02-09 05:44:23 +00:00
feat: step functions example
This commit is contained in:
@@ -636,6 +636,52 @@ Such roles need to allow being assumed by the `states.amazonaws.com` Principal.
|
||||
|
||||
If wanting to send logs to CloudWatch, the execution role must be able to access the log group.
|
||||
|
||||
<details style='padding: 0 0 1rem 1rem'>
|
||||
<summary>Example: get an RDS DB instance's information and pass it as a specific attribute
|
||||
|
||||
```json
|
||||
{
|
||||
"Comment": "Get an RDS DB instance's information and pass it as a specific attribute",
|
||||
"StartAt": "Get RDS DB Instance information",
|
||||
"States": {
|
||||
"Get RDS DB Instance information": {
|
||||
"Type": "Task",
|
||||
"Arguments": {
|
||||
"DbInstanceIdentifier": "some-rds-db-instance-identifier"
|
||||
},
|
||||
"Resource": "arn:aws:states:::aws-sdk:rds:describeDBInstances",
|
||||
"End": true,
|
||||
"Output": {
|
||||
"RdsDbInstanceInformation": "{% $states.result.DbInstances[0] %}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"QueryLanguage": "JSONata"
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
Unless one knows exactly what one is doing, prefer setting arguments from the service's Console to have _some_ level of
|
||||
suggestions.
|
||||
|
||||
<details>
|
||||
<summary>FIXME - using variables in DescribeDBSnapshots</summary>
|
||||
|
||||
```json
|
||||
{
|
||||
"DbInstanceIdentifier": "{% $states.input.ProdDBInstanceInfo.DbInstanceIdentifier %}"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"AvailableDBSnapshots": "{% $states.result.DbSnapshots[Status='available'] %}"
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Resource constraints
|
||||
|
||||
| Data type | Component | Summary | Description | Type | Length | Pattern | Required |
|
||||
|
||||
92
knowledge base/jsonata.md
Normal file
92
knowledge base/jsonata.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# JSONata
|
||||
|
||||
> TODO
|
||||
|
||||
JSON query and transformation language.
|
||||
|
||||
<!-- Remove this line to uncomment if used
|
||||
## Table of contents <!-- omit in toc -->
|
||||
|
||||
1. [TL;DR](#tldr)
|
||||
1. [Further readings](#further-readings)
|
||||
1. [Sources](#sources)
|
||||
|
||||
## TL;DR
|
||||
|
||||
```plaintext
|
||||
# Concatenate strings
|
||||
someAttribute & 'someSuffix'
|
||||
'somePrefix' & someAttribute
|
||||
'somePrefix' & someAttribute & 'someSuffix'
|
||||
|
||||
# Join strings
|
||||
$join(['somePrefix', someAttribute, 'someSuffix'], '-')
|
||||
|
||||
# Filter array of objects by attribute's value
|
||||
users[role = "admin"]
|
||||
users[role = "admin" and name = "Alice"].name
|
||||
|
||||
# Filter events with timestamp value in the last week
|
||||
events[$toMillis(timestamp) >= $toMillis($now()) - (60 * 60 * 7 * 24 * 1000)]
|
||||
|
||||
# Get a random value between 0 included and 1 excluded (0<=X<1)
|
||||
$random()
|
||||
|
||||
# Get a random object from a list
|
||||
# Lists are 0-indexed
|
||||
users[$floor($random()*$count($users))]
|
||||
```
|
||||
|
||||
<!-- Uncomment if used
|
||||
<details>
|
||||
<summary>Setup</summary>
|
||||
|
||||
```sh
|
||||
```
|
||||
|
||||
</details>
|
||||
-->
|
||||
|
||||
<!-- Uncomment if used
|
||||
<details>
|
||||
<summary>Usage</summary>
|
||||
|
||||
```sh
|
||||
```
|
||||
|
||||
</details>
|
||||
-->
|
||||
|
||||
<!-- Uncomment if used
|
||||
<details>
|
||||
<summary>Real world use cases</summary>
|
||||
|
||||
```sh
|
||||
```
|
||||
|
||||
</details>
|
||||
-->
|
||||
|
||||
## Further readings
|
||||
|
||||
- [Website]
|
||||
- [Codebase]
|
||||
|
||||
### Sources
|
||||
|
||||
- [Documentation]
|
||||
|
||||
<!--
|
||||
Reference
|
||||
═╬═Time══
|
||||
-->
|
||||
|
||||
<!-- In-article sections -->
|
||||
<!-- Knowledge base -->
|
||||
<!-- Files -->
|
||||
<!-- Upstream -->
|
||||
[Codebase]: https://github.com/jsonata-js/jsonata
|
||||
[Documentation]: https://docs.jsonata.org/
|
||||
[Website]: https://jsonata.org/
|
||||
|
||||
<!-- Others -->
|
||||
@@ -0,0 +1,219 @@
|
||||
import * as pulumi from "@pulumi/pulumi";
|
||||
import * as aws from "@pulumi/aws";
|
||||
|
||||
const iamRole: pulumi.Output<aws.iam.GetRoleResult> = aws.iam.getRoleOutput({
|
||||
name: 'SomeServiceRole',
|
||||
});
|
||||
|
||||
// -----------------
|
||||
|
||||
/**
|
||||
* Base type for Step Function states.
|
||||
*
|
||||
* States are elements in a state machine.\
|
||||
* A state is referred to by its name, which can be any string, but which must be unique within the scope of the entire
|
||||
* state machine.
|
||||
*
|
||||
* States take input from their own invocation or a previous state.\
|
||||
* States can filter their input and manipulate the output that is sent to the next state.
|
||||
*
|
||||
* Refer <https://docs.aws.amazon.com/step-functions/latest/dg/workflow-states.html>.
|
||||
*/
|
||||
type StateMachineBaseState = {
|
||||
Type: string;
|
||||
Comment?: string;
|
||||
Next?: string;
|
||||
End?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Choice state.\
|
||||
* Enables conditional branching.
|
||||
*/
|
||||
interface StateMachineChoiceState extends StateMachineBaseState {
|
||||
Type: "Choice";
|
||||
Choices: Record<string, any>[];
|
||||
Default: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Branch type for Parallel states.\
|
||||
* Itself a smaller state machine.
|
||||
*/
|
||||
type StateMachineParallelBranch = {
|
||||
StartAt: string;
|
||||
States: Record<string, StateMachineStepState>;
|
||||
}
|
||||
/**
|
||||
* Parallel state.\
|
||||
* Runs other step states in parallel.
|
||||
*/
|
||||
interface StateMachineParallelState extends StateMachineBaseState {
|
||||
Type: "Parallel";
|
||||
Branches: StateMachineParallelBranch[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Task state.\
|
||||
* Runs a service integration or Lambda function.
|
||||
*/
|
||||
interface StateMachineTaskState extends StateMachineBaseState {
|
||||
Type: "Task";
|
||||
Resource: string;
|
||||
Arguments?: Record<string, any>;
|
||||
Output?: Record<string, any>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wait state.\
|
||||
* Pauses execution for a fixed duration or until a specified time or date.
|
||||
*/
|
||||
interface StateMachineWaitState extends StateMachineBaseState {
|
||||
Type: "Wait";
|
||||
Seconds?: number;
|
||||
Timestamp?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Union type for Step Function states.
|
||||
*/
|
||||
type StateMachineStepState =
|
||||
| StateMachineChoiceState
|
||||
| StateMachineParallelState
|
||||
| StateMachineTaskState
|
||||
| StateMachineWaitState;
|
||||
|
||||
/**
|
||||
* Generic State Machine definition.
|
||||
*/
|
||||
interface StateMachineDefinition {
|
||||
Comment?: string;
|
||||
QueryLanguage?: string;
|
||||
StartAt: string;
|
||||
States: Record<string, StateMachineStepState>;
|
||||
};
|
||||
|
||||
// -----------------
|
||||
|
||||
const changeClonedDbInstancePassword: StateMachineTaskState = {
|
||||
Type: "Task",
|
||||
Resource: "arn:aws:states:::aws-sdk:rds:modifyDBInstance",
|
||||
Arguments: {
|
||||
DbInstanceIdentifier: "{% $states.input.ClonedDBInstance.DbInstanceIdentifier %}",
|
||||
MasterUserPassword: "some-Secur3-Password",
|
||||
ApplyImmediately: true,
|
||||
},
|
||||
End: true,
|
||||
};
|
||||
|
||||
const checkClonedDbInstanceIsAvailable: StateMachineChoiceState = {
|
||||
Type: "Choice",
|
||||
Choices: [
|
||||
{
|
||||
Condition: "{% $states.input.ClonedDBInstance.DBInstanceStatus in ['available'] %}",
|
||||
Next: "ChangeClonedDBInstancePassword",
|
||||
},
|
||||
],
|
||||
Default: "WaitForClonedDBInstanceNextCheck",
|
||||
};
|
||||
|
||||
const createClonedDbInstance: StateMachineTaskState = {
|
||||
Type: "Task",
|
||||
Resource: "arn:aws:states:::aws-sdk:rds:restoreDBInstanceToPointInTime",
|
||||
Arguments: {
|
||||
SourceDBInstanceIdentifier: "{% $states.input.ExistingDBInstanceInfo.DbInstanceIdentifier %}",
|
||||
UseLatestRestorableTime: true,
|
||||
TargetDBInstanceIdentifier: "{% $join([$states.input.ExistingDBInstanceInfo.DbInstanceIdentifier, 'clone'], '-') %}",
|
||||
Engine: "postgres",
|
||||
MultiAZ: false,
|
||||
AvailabilityZone: "eu-west-1a",
|
||||
DbSubnetGroupName: "default",
|
||||
PubliclyAccessible: false,
|
||||
VpcSecurityGroupIds: [],
|
||||
DbParameterGroupName: "{% $states.input.ExistingDBInstanceInfo.DbParameterGroups[0].DbParameterGroupName %}",
|
||||
OptionGroupName: "{% $states.input.ExistingDBInstanceInfo.OptionGroupMemberships[0].OptionGroupName %}",
|
||||
StorageType: "gp3",
|
||||
DedicatedLogVolume: false,
|
||||
DbInstanceClass: "db.t4g.medium",
|
||||
DeletionProtection: false,
|
||||
AutoMinorVersionUpgrade: false,
|
||||
},
|
||||
Output: {
|
||||
ClonedDBInstance: "{% $states.result.DbInstance %}",
|
||||
},
|
||||
Next: "GetClonedDBInstanceState",
|
||||
};
|
||||
|
||||
const getClonedDbInstanceState: StateMachineTaskState = {
|
||||
Type: "Task",
|
||||
Resource: "arn:aws:states:::aws-sdk:rds:describeDBInstances",
|
||||
Arguments: {
|
||||
DbInstanceIdentifier: "{% $states.input.ClonedDBInstance.DbInstanceIdentifier %}",
|
||||
},
|
||||
Output: {
|
||||
ClonedDBInstance: "{% $states.result.DbInstances[0] %}",
|
||||
},
|
||||
Next: "CheckClonedDBInstanceIsAvailable",
|
||||
};
|
||||
|
||||
const getExistingDbInstanceInfo: StateMachineTaskState = {
|
||||
Type: "Task",
|
||||
Resource: "arn:aws:states:::aws-sdk:rds:describeDBInstances",
|
||||
Arguments: {
|
||||
DbInstanceIdentifier: "some-existing-rds-instance",
|
||||
},
|
||||
Output: {
|
||||
ExistingDBInstanceInfo: "{% $states.result.DbInstances[0] %}",
|
||||
},
|
||||
Next: "ParallelZone",
|
||||
};
|
||||
|
||||
const waitForClonedDbInstanceNextCheck: StateMachineWaitState = {
|
||||
Type: "Wait",
|
||||
Seconds: 60,
|
||||
Next: "GetClonedDBInstanceState",
|
||||
};
|
||||
|
||||
const parallelZone: StateMachineParallelState = {
|
||||
Type: "Parallel",
|
||||
Branches: [
|
||||
{
|
||||
StartAt: "CreateClonedDBInstance",
|
||||
States: {
|
||||
CreateClonedDBInstance: createClonedDbInstance,
|
||||
GetClonedDBInstanceState: getClonedDbInstanceState,
|
||||
CheckClonedDBInstanceIsAvailable: checkClonedDbInstanceIsAvailable,
|
||||
WaitForClonedDBInstanceNextCheck: waitForClonedDbInstanceNextCheck,
|
||||
ChangeClonedDBInstancePassword: changeClonedDbInstancePassword,
|
||||
},
|
||||
},
|
||||
// FIXME: another branch here
|
||||
],
|
||||
End: true,
|
||||
};
|
||||
|
||||
const stateMachineDefinition: StateMachineDefinition = {
|
||||
QueryLanguage: "JSONata",
|
||||
States: {
|
||||
GetExistingDBInstanceInfo: getExistingDbInstanceInfo,
|
||||
ParallelZone: parallelZone,
|
||||
},
|
||||
StartAt: "GetExistingDBInstanceInfo",
|
||||
};
|
||||
// pulumi.jsonStringify(stateMachineDefinition).apply(s => console.log(s))
|
||||
|
||||
const dbCloner_stateMachine: aws.sfn.StateMachine = new aws.sfn.StateMachine(
|
||||
'dbCloner',
|
||||
{
|
||||
name: 'DBCloner',
|
||||
roleArn: iamRole.arn,
|
||||
loggingConfiguration: {
|
||||
level: "OFF",
|
||||
},
|
||||
encryptionConfiguration: {
|
||||
type: "AWS_OWNED_KEY",
|
||||
},
|
||||
publish: false,
|
||||
definition: pulumi.jsonStringify(stateMachineDefinition),
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user