ROSTemplateFormatVersion: '2015-09-01'
Description:
  zh-cn: 该模板用于创建一个包含ECS实例群组与RDS PostgreSQL实例的阿里云环境，支持预付费和按需付费模式，配置实例类型、系统盘、安全组及数据库实例规格与存储，实现资源的自动化部署与初始化配置。
  en: This template is designed for provisioning an Alibaba Cloud environment comprising
    an ECS instance cluster and an RDS PostgreSQL instance, accommodating both prepaid
    and pay-as-you-go billing models. It facilitates the configuration of instance
    types, system disks, security groups, as well as the specification and storage
    of the database instance, thereby enabling automated resource deployment and initial
    setup.
# 定义参数
Parameters:
  # 付费类型：按量付费/包年包月
  PayType:
    Type: String
    Label:
      en: ECS Instance Charge Type
      zh-cn: 付费类型
    Default: PostPaid
    AllowedValues:
      - PostPaid
      - PrePaid
    AssociationProperty: ChargeType
    AssociationPropertyMetadata:
      LocaleKey: InstanceChargeType
  # 购买资源时长周期，只在付费类型为包年包月时显示
  PayPeriodUnit:
    Type: String
    Label:
      en: Pay Period Unit
      zh-cn: 购买资源时长周期
    Default: Month
    AllowedValues:
      - Month
      - Year
    AssociationProperty: PayPeriodUnit
    AssociationPropertyMetadata:
      Visible:
        Condition:
          'Fn::Not':
            'Fn::Equals':
              - '${PayType}'
              - PostPaid
  # 购买资源时长，只在付费类型为包年包月时显示
  PayPeriod:
    Type: Number
    Description:
      en: When the resource purchase duration is Month, the value of Period ranges from 1 to 9, 12, 24, 36, 48, or 60. <br><b><font color='red'> When ECS instance types are PrePaid valid </b></font>
      zh-cn: 当购买资源时长为Month时，Period取值：1~9 <br><b><font color='red'>当ECS实例类型为PrePaid有效</b></font>
    Label:
      en: Period
      zh-cn: 购买资源时长
    Default: 1
    AllowedValues:
      - 1
      - 2
      - 3
      - 4
      - 5
      - 6
      - 7
      - 8
      - 9
    AssociationProperty: PayPeriod
    AssociationPropertyMetadata:
      Visible:
        Condition:
          'Fn::Or':
            - 'Fn::Equals':
                - '${PayType}'
                - PrePaid
            - 'Fn::Equals':
                - '${PayType}'
                - undefined
  ZoneId:
    Type: String
    AssociationProperty: 'ALIYUN::ECS::Instance::ZoneId'
    Label:
      en: VSwitch Availability Zone
      zh-cn: 交换机可用区
  VpcId:
    AssociationProperty: 'ALIYUN::ECS::VPC::VPCId'
    Type: String
    Description:
      en: Please search the ID starting with (vpc-xxx) from console-Virtual
        Private Cloud
      zh-cn: 现有虚拟专有网络的实例ID
    Label:
      en: VPC ID
      zh-cn: 专有网络VPC实例ID
  VSwitchId:
    AssociationProperty: 'ALIYUN::ECS::VSwitch::VSwitchId'
    AssociationPropertyMetadata:
      VpcId: '${VpcId}'
      ZoneId: '${ZoneId}'
    Type: String
    Description:
      en: Instance ID of existing business network switches, console-Virtual
        Private Cloud-VSwitches under query
      zh-cn: 现有业务网络交换机的实例ID
    Label:
      en: VSwitch ID
      zh-cn: 交换机实例ID
  EcsInstanceType:
    Type: String
    Label:
      en: Instance Type
      zh-cn: 实例类型
    AssociationProperty: 'ALIYUN::ECS::Instance::InstanceType'
    AssociationPropertyMetadata:
      InstanceChargeType: '${PayType}'
  SystemDiskCategory:
    Type: String
    AllowedValues:
      - cloud_efficiency
      - cloud_ssd
      - cloud
      - cloud_essd
    Label:
      en: System Disk Category
      zh-cn: 系统盘类型
    Default: cloud_essd
    AssociationPropertyMetadata:
      LocaleKey: DiskCategory
  SystemDiskSize:
    Default: 40
    Type: Number
    Label:
      zh-cn: 系统盘空间 (GB)
      en: System Disk Space (GB)
  InstanceCount:
    Type: Number
    Label:
      en: Instance Count
      zh-cn: Node节点数量
    Default: 1
  DBInstanceClass:
    Label:
      zh-cn: 实例规格
      en: DB Instance Class
    AssociationProperty: 'ALIYUN::RDS::Instance::InstanceType'
    AssociationPropertyMetadata:
      Engine: PostgreSQL
      ZoneId: ${ZoneId}
    Type: String
    Description:
      zh-cn: 根据数据库引擎的类型和可用的区域支持选择实例规格；<br>请参见详细信息：<a
        href='https://help.aliyun.com/document_detail/26312.html'
        target='_blank'><b><font color='blue'>实例规格表</font></b></a>
      en: Select the instance specification based on the type of database engine
        and the available area support;<br>see detail <a
        href='https://www.alibabacloud.com/help/doc-detail/26312.html'
        target='_blank'><b><font color='blue'>Instance specification
        sheet</font></b></a>
    Default: pg.x2.large.2c
  DBInstanceStorage:
    Label:
      zh-cn: 实例存储
      en: Storage
    Type: Number
    Description:
      zh-cn: RDS实例大小范围为20-2000，每5个增量，单位为GB
      en: The size range of RDS instances is 20 - 2000, Incrementing in every 5,
        unit GB
    MinValue: 20
    MaxValue: 2000
    ConstraintDescription:
      zh-cn: RDS实例大小范围为20-2000，每5个增量，单位为GB
      en: The size range of RDS instances is 20 - 2000, Incrementing in every 5,
        unit GB
    Default: 200
  DBInstanceStorageType:
    Label:
      zh-cn: 实例存储类型
      en: Storage Type
    Type: String
    Description:
      zh-cn: 实例存储类型；<br>请参见详细信息：<a href='https://help.aliyun.com/document_detail/69795.html' target='_blank'><b><font color='blue'>存储类型</font></b></a>
      en: The storage type of DB instance; see detail <a href='https://www.alibabacloud.com/help/en/apsaradb-for-rds/latest/storage-types' target='_blank'><b><font color=''blue''>Storage types</font></b></a>'
    AllowedValues:
      - local_ssd
      - cloud_ssd
      - cloud_essd
      - cloud_essd2
      - cloud_essd3
  DBCategory:
    Label:
      zh-cn: 实例系列
      en: DB Category
    Type: String
    AllowedValues:
      - Basic
      - HighAvailability
      - AlwaysOn
      - Finance
    AssociationPropertyMetadata:
      LocaleKey: RDSCategory
  DBMasterUsername:
    Type: String
    Description:
      en: Primary account name of the database instance.
      zh-cn: 数据库实例的主账号名称。
    ConstraintDescription:
      en: Consist of 2 to 16 characters of lowercase letters, underline. Must
        begin with a letter and be end with an alphanumeric character
      zh-cn: 由 2 到 16 个小写字母组成，下划线。必须以字母开头，以字母数字字符结尾
    Label:
      zh-cn: 数据库账号名称
      en: DB Username
    Default: rdsuser
    MaxLength: 16
    MinLength: 2
  DBMasterPassword:
    NoEcho: true
    Type: String
    Description:
      en: Server login password, Length 8-30, must contain three(Capital letters,
        lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ Special
        symbol in)
      zh-cn: 服务器登录密码,长度8-30，必须包含三项（大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;<>,.?/
        中的特殊符号）
    Label:
      en: Instance Password
      zh-cn: 实例密码
    ConstraintDescription:
      en: Length 8-30, must contain three(Capital letters, lowercase letters,
        numbers, ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ Special symbol in)
      zh-cn: '长度8-30，必须包含三项（大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ 中的特殊符号）'
    AllowedPattern: '^[a-zA-Z0-9-\(\)\`\~\!\@\#\$\%\^\&\*\_\-\+\=\|\{\}\[\]\:\;\<\>\,\.\?\/]*$'
    MinLength: 8
    MaxLength: 30
  InstancePassword:
    NoEcho: true
    Type: String
    Description:
      en: Server login password, Length 8-30, must contain three(Capital letters, lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ Special symbol in)
      zh-cn: 服务器登录密码,长度8-30，必须包含三项（大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ 中的特殊符号）
    Label:
      en: Instance Password
      zh-cn: 实例密码
    ConstraintDescription:
      en: Length 8-30, must contain three(Capital letters, lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ Special symbol in)
      zh-cn: 长度8-30，必须包含三项（大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;<>,.?/ 中的特殊符号）
    AssociationProperty: ALIYUN::ECS::Instance::Password
    AllowedPattern: '^[a-zA-Z0-9-\(\)\`\~\!\@\#\$\%\^\&\*\_\-\+\=\|\{\}\[\]\:\;\<\>\,\.\?\/]*$'
    MinLength: 8
    MaxLength: 30
Resources:
  EcsSecurityGroup:
    Type: ALIYUN::ECS::SecurityGroup
    Properties:
      SecurityGroupName:
        Ref: ALIYUN::StackName
      VpcId:
        Ref: VpcId
      SecurityGroupEgress:
        - PortRange: '-1/-1'
          Priority: 1
          IpProtocol: all
          DestCidrIp: 0.0.0.0/0
          NicType: intranet
  Database:
    Type: 'ALIYUN::RDS::DBInstance'
    Properties:
      ZoneId:
        Ref: ZoneId
      VpcId:
        Ref: VpcId
      VSwitchId:
        Ref: VSwitchId
      Engine: PostgreSQL
      EngineVersion: '14.0'
      DBInstanceClass:
        Ref: DBInstanceClass
      DBInstanceStorage:
        Ref: DBInstanceStorage
      DBInstanceStorageType:
        Ref: DBInstanceStorageType
      Category:
        Ref: DBCategory
      DBInstanceNetType: Intranet
      MasterUserPassword:
        Ref: DBMasterPassword
      MasterUsername:
        Ref: DBMasterUsername
      PayType:
        Ref: PayType
      PeriodType:
        Ref: PayPeriodUnit
      Period:
        Ref: PayPeriod
      SecurityIPList:
        'Fn::Join':
          - ','
          - 'Fn::GetAtt':
              - InstanceGroup
              - PrivateIps
  InstanceGroup:
    Type: 'ALIYUN::ECS::InstanceGroup'
    Properties:
      InstanceName:
        'Fn::Join':
          - '-'
          - - Ref: 'ALIYUN::StackName'
            - '[1,4]'
      IoOptimized: optimized
      InstanceChargeType:
        Ref: PayType
      PeriodUnit:
        Ref: PayPeriodUnit
      Period:
        Ref: PayPeriod
      ZoneId:
        Ref: ZoneId
      VpcId:
        Ref: VpcId
      VSwitchId:
        Ref: VSwitchId
      SecurityGroupId:
        Ref: EcsSecurityGroup
      SystemDiskCategory:
        Ref: SystemDiskCategory
      SystemDiskSize:
        Ref: SystemDiskSize
      MaxAmount:
        Ref: InstanceCount
      Password:
        Ref: InstancePassword
      ImageId: centos_7
      InstanceType:
        Ref: EcsInstanceType
      AllocatePublicIP: false
      UserData: '-|'
  WaitCondition:
    Type: 'ALIYUN::ROS::WaitCondition'
    DependsOn:
      - Database
      - InstanceGroup
    Properties:
      Count: 1
      Handle:
        Ref: WaitConditionHandle
      Timeout: 300
  WaitConditionHandle:
    Type: 'ALIYUN::ROS::WaitConditionHandle'
  InstanceRunCommand:
    Type: 'ALIYUN::ECS::RunCommand'
    Properties:
      CommandContent:
        'Fn::Sub':
          - |
            #!/bin/bash
            cat >> /root/conf.txt << "EOF"
            DBMasterUsername=${DBMasterUsername}
            DBMasterPassword=${DBMasterPassword}
            DBConnectString=${DBConnectString}
            EOF

            # 继续进行初始化，数据库的初始化用shell pg_dump完成
            # psql -h 127.0.0.1 -U postgres -p 5432 postgres  < /usr/local/pgsql/data/db_dump.sql
            # init.sh /root/conf.txt
            # init.sh ${DBMasterUsername} ${DBMasterPassword} ${DBConnectString} 也是可以的

            # 执行成功回调WaitCondition结束waitCondition的等待
            ${CurlCli} -d "{\"Data\" : \"Success\", \"status\" : \"SUCCESS\"}"
          - DBMasterUsername:
              Ref: DBMasterUsername
            DBMasterPassword:
              Ref: DBMasterPassword
            DBConnectString:
              'Fn::GetAtt':
                - Database
                - InnerConnectionString
            CurlCli:
              'Fn::GetAtt':
                - WaitConditionHandle
                - CurlCli
      Type: RunShellScript
      InstanceIds:
        'Fn::GetAtt':
          - InstanceGroup
          - InstanceIds
      Timeout: '300'
Metadata:
  'ALIYUN::ROS::Interface':
    ParameterGroups:
      - Parameters:
          - VpcId
          - ZoneId
          - VSwitchId
        Label:
          default:
            zh-cn: 选择已有基础资源配置
            en: Choose existing Infrastructure Configuration
      - Parameters:
          - PayType
          - PayPeriodUnit
          - PayPeriod
        Label:
          default:
            en: PayType Configuration
            zh-cn: 付费类型配置
      - Parameters:
          - EcsInstanceType
          - SystemDiskCategory
          - SystemDiskSize
          - InstanceCount
        Label:
          default:
            en: Instance
            zh-cn: ECS实例配置
      - Parameters:
          - DBInstanceClass
          - DBInstanceStorage
          - DBInstanceStorageType
          - DBCategory
          - DBMasterUsername
          - DBMasterPassword
        Label:
          default:
            en: Database
            zh-cn: 数据库配置