ROSTemplateFormatVersion: '2015-09-01'
Description:
  zh-cn: 创建一个付费灵活、配置自定义的ECS实例，搭载MySQL数据库，自动分区、安装与配置，支持公有IP访问。
  en: Create a pay-as-you-go, customizable ECS instance equipped with a MySQL database,
    featuring automatic partitioning, installation, and configuration, with support
    for public IP access.
# 定义参数
Parameters:
  # 可用区
  ZoneId:
    Type: String
    AssociationProperty: ALIYUN::ECS::Instance:ZoneId
    Label:
      en: VSwitch Available Zone
      zh-cn: 可用区
  # 付费类型：按量付费/包年包月
  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
    Label:
      en: Period
      zh-cn: 购买资源时长
    Default: 1
    AllowedValues:
      - 1
      - 2
      - 3
      - 4
      - 5
      - 6
      - 7
      - 8
      - 9
    AssociationProperty: PayPeriod
    AssociationPropertyMetadata:
      Visible:
        Condition:
          Fn::Not:
            Fn::Equals:
              - ${PayType}
              - PostPaid
  # 数据盘类型
  DataDiskCategory:
    Type: String
    AllowedValues:
      - cloud_efficiency        # 高效云盘
      - cloud_ssd               # SSD云盘
      - cloud                   # 普通云盘
      - cloud_essd              # ESSD云盘
    Default: cloud_efficiency
    Label:
      en: Disk Type
      zh-cn: 数据盘类型
    AssociationPropertyMetadata:
      LocaleKey: DiskCategory
  # 数据盘空间
  DataDiskSize:
    Type: Number
    Label:
      en: Data Disk Space
      zh-cn: 数据盘空间
    MinValue: 20
    MaxValue: 500
    Default: 40
  # 数据库root账户密码
  Password:
    # 查询该参数时只输出星号（*）
    NoEcho: true
    Type: String
    Description:
      en: 'Database root account password, 8-32 characters, including uppercase and lowercase letters, numbers and special symbols (including: !@#$%^&*-+=_).'
      zh-cn: 数据库root账户密码，长度8-32个字符，可包含大小字母、数字及特殊符号（包含：!@#$%^&*-+=_）。
    Label:
      en: Root Account Password
      zh-cn: 数据库root账户密码
    ConstraintDescription:
      en: '8-32 characters, including uppercase and lowercase letters, numbers and special symbols (including: !@#$%^&*-+=_)'
      zh-cn: 8-32个字符，可包含大小字母、数字及特殊符号（包含：!@#$%^&*-+=_）
    AssociationProperty: ALIYUN::ECS::Instance::Password
    AllowedPattern: '^[a-zA-Z0-9-\!\@\#\$\%\^\&\*\-\+\=\_]*$'
    MinLength: 8
    MaxLength: 30
  # 专有网络VPC实例ID
  VpcId:
    AssociationProperty: ALIYUN::ECS::VPC::VPCId
    Type: String
    Label:
      en: VPC ID
      zh-cn: 专有网络VPC实例ID
  # 交换机实例ID
  VSwitchId:
    AssociationProperty: ALIYUN::ECS::VSwitch::VSwitchId
    AssociationPropertyMetadata:
      VpcId: ${VpcId}
      ZoneId: ${ZoneId}
    Type: String
    Label:
      en: VSwitch ID
      zh-cn: 交换机实例ID
  # Ecs实例类型
  EcsInstanceType:
    Type: String
    Label:
      en: Instance Type
      zh-cn: Ecs实例类型
    AssociationProperty: ALIYUN::ECS::Instance::InstanceType
# 定义资源
Resources:
  # 定义WaitCondition和WaitConditionHandle来等待命令在Ecs中执行完毕部署成功
  WaitCondition:
    Type: ALIYUN::ROS::WaitCondition
    Properties:
      Count: 1
      Handle:
        Ref: WaitConditionHandle
      Timeout: 1800
  WaitConditionHandle:
    Type: ALIYUN::ROS::WaitConditionHandle
  EcsSecurityGroup:
    Type: ALIYUN::ECS::SecurityGroup
    Properties:
      SecurityGroupName:
        Ref: ALIYUN::StackName
      SecurityGroupIngress:
        - Priority: 1
          PortRange: 3306/3306
          NicType: intranet
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
      VpcId:
        Ref: VpcId
  # Ecs实例
  EcsInstance:
    Type: ALIYUN::ECS::Instance
    Properties:
      # 实例名称
      InstanceName:
        Ref: ALIYUN::StackName
      # I/O优化实例
      IoOptimized: optimized
      DiskMappings:
        - Category:
            Ref: DataDiskCategory
          Device: /dev/xvdb
          Size:
            Ref: DataDiskSize
      SystemDiskSize: 40
      # cloud-init执行用户命令
      # /var/log/cloud-init.log /var/log/cloud-init-output.log 可以看到执行日志
      # /var/lib/cloud/instance/scripts/part-001 为具体的脚本 可以sh 执行来排查问题
      UserData:
        Fn::Sub:
          - |
            #!/bin/sh

            # sleep一段时间确保网络就绪
            sleep 10

            # 对数据盘进行分区
            cat >> /root/InitDataDisk.sh << "EOF"
            #!/bin/bash
            echo "p
            n
            p



            w
            " |  fdisk -u /dev/vdb
            EOF
            /bin/bash /root/InitDataDisk.sh
            rm -f /root/InitDataDisk.sh
            # 在新分区上创建文件系统
            mkfs.ext4 /dev/vdb1
            # 创建目录，MySQL将安装在该目录下
            mkdir /data1
            # 挂载文件系统
            mount /dev/vdb1 /data1
            # 向 /etc/fstab 写入新分区信息
            echo /dev/vdb1 /data1 ext4 defaults,nodelalloc,noatime 0 2 >> /etc/fstab
            cd /data1/

            # 安装社区版MySQL
            wget http://repo.mysql.com/mysql-community-release-el6-5.noarch.rpm
            rpm -ivh mysql-community-release-el6-5.noarch.rpm
            yum repolist all | grep mysql
            yum install mysql-community-server -y

            # 启动MySQL服务
            service mysqld start

            # 以超级用户身份登入，创建admin用户，并允许admin用户以Password为密码远程登录
            mysqladmin -u root password '${Password}'
            echo "create database test character set utf8 collate utf8_bin;" > ./test.sql
            echo "CREATE USER 'admin'@'%' IDENTIFIED BY '${Password}';" >> ./test.sql
            echo "GRANT ALL PRIVILEGES ON *.* TO 'admin'@'%' WITH GRANT OPTION;" >> ./test.sql
            mysql -u root -p'${Password}' < ./test.sql

            # 将MySQL的配置和数据路径移动到数据盘上
            systemctl stop mysqld
            rsync -av /var/lib/mysql /data1
            # 修改配置文件
            sed -i 's/\/var\/lib/\/data1/g' /etc/my.cnf
            echo -e '\n' >> /etc/my.cnf
            echo '[client]' >> /etc/my.cnf
            echo 'port=3306' >> /etc/my.cnf
            echo 'socket=/data1/mysql/mysql.sock' >> /etc/my.cnf
            # 重启MySQL
            systemctl start mysqld

            # 执行成功回调WaitCondition结束WaitCondition的等待
            ${CurlCli} -d "{\"Data\" : \"SUCCESS\", \"Status\" : \"SUCCESS\"}"

          # 获取到WaitConditionHandle的地址放到 ${CurlCli}变量里
          - CurlCli:
              Fn::GetAtt:
                - WaitConditionHandle
                - CurlCli
            # 数据库root账户密码
            Password:
              Ref: Password
      # 付费方式：按量付费
      InstanceChargeType:
        Ref: PayType
      PeriodUnit:
        Ref: PayPeriodUnit
      Period:
        Ref: PayPeriod
      # 系统盘类型：高效云盘
      SystemDiskCategory: cloud_efficiency
      # 实例名称
      InstanceName:
        Fn::Join:
          - '-'
          - - mysql
            - Ref: ALIYUN::StackName
      VpcId:
        Ref: VpcId
      SecurityGroupId:
        Ref: EcsSecurityGroup
      VSwitchId:
        Ref: VSwitchId
      # 指定CentOS 7.9镜像，如果修改镜像，UserData脚本需要进行适配
      ImageId: "centos_7_9_x64_20G_alibase_20220727.vhd"
      InstanceType:
        Ref: EcsInstanceType
      # 主机名
      HostName: mysql-public-ip
      # Ecs登录密码
      Password:
        Ref: Password
      # 是否为实例分配公网IP
      AllocatePublicIP: true
# 定义输出
Outputs:
  # 将数据库连接地址显示在控制台
  DBConnectionAddress:
    Value:
      # 将Ecs的公网IP拼接成数据库连接地址
      Fn::Sub:
        - mysql://${Domain}:3306
        - Domain:
            Fn::GetAtt:
              - EcsInstance
              - PublicIp
# 定义元数据
Metadata:
  ALIYUN::ROS::Interface:
    # 定义资源分组，创建服务实例时，同一分组的参数分布在一起
    ParameterGroups:
      - Parameters:
          - ZoneId
          - Password
        Label:
          en: Basic Configuration
          zh-cn: 基础配置
      - Parameters:
          - PayType
          - PayPeriodUnit
          - PayPeriod
        Label:
          en: PayType Configuration
          zh-cn: 付费类型配置
      - Parameters:
          - EcsInstanceType
        Label:
          en: Instance Type
          zh-cn: 实例规格
      - Parameters:
          - DataDiskCategory
          - DataDiskSize
        Label:
          en: Data Disk Configuration
          zh-cn: 数据盘配置
      - Parameters:
          - VpcId
          - VSwitchId
        Label:
          en: Network Configuration
          zh-cn: 网络配置