ROSTemplateFormatVersion: '2015-09-01'
Description:
  zh-cn: 部署单台优化的Redis实例，含付费方式选择、自定义磁盘大小、网络配置与安全设置，支持自动创建安全组与公网访问控制。
  en: Deploy a single, optimized Redis instance with options for payment plans, customizable
    disk size, network configurations, and security settings. This deployment supports
    the automatic creation of security groups and control of public network access.
# 参数配置
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::Not:
            Fn::Equals:
              - ${PayType}
              - PostPaid
  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
  AutoCreateSecurityGroup:
    Type: Boolean
    Default: true
    Label:
      zh-cn: 自动创建安全组
      en: auto create security group
  SecurityGroupId:
    Type: String
    AssociationProperty: ALIYUN::ECS::SecurityGroup::SecurityGroupId
    AssociationPropertyMetadata:
      VpcId: ${VpcId}
      Visible:
        Condition:
          Fn::Equals:
            - ${AutoCreateSecurityGroup}
            - false
    Default: ''
    Description:
      en: Please search the business security group ID starting with(sg-xxx)from console-ECS-Network & Security
      zh-cn: 现有业务安全组的实例ID
    Label:
      en: Business Security Group ID
      zh-cn: 业务安全组ID
  EcsInstanceType:
    Type: String
    Label:
      en: Instance Type
      zh-cn: 实例类型
    AssociationProperty: ALIYUN::ECS::Instance::InstanceType
    AssociationPropertyMetadata:
      ZoneId: ${ZoneId}
      InstanceChargeType: ${InstanceChargeType}
  SystemDiskSize:
    Default: 40
    Type: Number
    Description:
      zh-cn: 系统盘大小, 取值范围：[40, 500], 单位：GB。
      en: 'System disk size of each node, range of values: 40-500, units: GB.'
    MinValue: 40
    MaxValue: 500
    Label:
      zh-cn: 系统盘空间
      en: System Disk Space
  DataDiskSize:
    Default: 40
    Type: Number
    Description:
      zh-cn: 数据盘大小, 取值范围：[40, 500], 单位：GB。
      en: 'System disk size of each node, range of values: 40-500, units: GB.'
    MinValue: 40
    MaxValue: 500
    Label:
      zh-cn: 数据盘空间
      en: Data Disk Space
  AllocatePublicIp:
    Default: false
    Type: Boolean
    Label:
      zh-cn: 开启公网IP
      en: allocate public ip
  InternetMaxBandwidthOut:
    Default: 0
    Type: Number
    Label:
      zh-cn: 流量公网带宽
      en: Internet Max Bandwidth Out
    MinValue: 0
    MaxValue: 100
    Description:
      zh-cn: 取值范围0-100, 0为不开公网ip
      en: no public ip if zero
    AssociationPropertyMetadata:
      Visible:
        Condition:
          Fn::Equals:
            - ${AllocatePublicIp}
            - true
  InternetChargeType:
    Default: PayByTraffic
    Type: String
    Label:
      zh-cn: 流量付费类型
      en: Internet Charge Type
    AllowedValues:
      - PayByBandwidth
      - PayByTraffic
    AssociationPropertyMetadata:
      LocaleKey: InternetChargeType
      Visible:
        Condition:
          Fn::Equals:
            - ${AllocatePublicIp}
            - true
  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，必须包含三项（大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号）
    AllowedPattern: '[0-9A-Za-z\_\-\&:;''<>,=%`~!@#\(\)\$\^\*\+\|\{\}\[\]\.\?\/]+$'
    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，必须包含三项（大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号）
    MinLength: 8
    MaxLength: 30
    AssociationProperty: ALIYUN::ECS::Instance::Password
  RedisPassword:
    NoEcho: true
    Type: String
    AllowedPattern: '[0-9A-Za-z\_\-\&:;''<>,=%`~!@#\(\)\$\^\*\+\|\{\}\[\]\.\?\/]+$'
    Label:
      en: Redis Login Password
      zh-cn: Redis密码
    ConstraintDescription:
      en: Length 8-30, must contain three(Capital letters, lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in)
      zh-cn: 长度8-30，必须包含三项（大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号）
    MinLength: 8
    MaxLength: 30
    AssociationProperty: ALIYUN::ECS::Instance::Password
Conditions:
  IfAutoCreateSecurityGroup:
    Fn::Equals:
      - Ref: AutoCreateSecurityGroup
      - true
  IfAllocatePublicIp:
    Fn::Equals:
      - Ref: AllocatePublicIp
      - true
# 资源配置
Resources:
  EcsSecurityGroup:
    Type: ALIYUN::ECS::SecurityGroup
    Condition: IfAutoCreateSecurityGroup
    Properties:
      SecurityGroupName:
        Ref: ALIYUN::StackName
      VpcId:
        Ref: VpcId
      # 只开放访问外网的规则
      SecurityGroupEgress:
        - PortRange: '-1/-1'
          Priority: 1
          IpProtocol: all
          DestCidrIp: 0.0.0.0/0
          NicType: intranet
      SecurityGroupIngress:
        Fn::If:
          - IfAllocatePublicIp
          - - PortRange: 6379/6379
              Priority: 1
              SourceCidrIp: 0.0.0.0/0
              IpProtocol: tcp
              NicType: internet
          - Ref: ALIYUN::NoValue
  # 定义waitCondition和waitConditionHandle来等待跳板机命令执行完毕部署成功
  WaitCondition:
    Type: ALIYUN::ROS::WaitCondition
    Properties:
      Count: 1
      Handle:
        Ref: WaitConditionHandle
      Timeout: 300
  WaitConditionHandle:
    Type: ALIYUN::ROS::WaitConditionHandle
  EcsInstanceGroup:
    Type: ALIYUN::ECS::InstanceGroup
    Properties:
      ZoneId:
        Ref: ZoneId
      # 实例名
      InstanceName:
        Fn::Join:
          - '-'
          - - Ref: ALIYUN::StackName
            - '[1,4]'
      IoOptimized: optimized
      # 付费类型
      InstanceChargeType:
        Ref: PayType
      PeriodUnit:
        Ref: PayPeriodUnit
      Period:
        Ref: PayPeriod
      # 网络配置
      VpcId:
        Ref: VpcId
      VSwitchId:
        Ref: VSwitchId
      SecurityGroupId:
        Fn::If:
          - IfAutoCreateSecurityGroup
          - Ref: EcsSecurityGroup
          - Ref: SecurityGroupId
      # 磁盘类型和大小
      SystemDiskCategory: cloud_essd
      SystemDiskSize:
        Ref: SystemDiskSize
      DiskMappings:
        - Category: cloud_essd
          Size:
            Ref: DataDiskSize
      MaxAmount: 1
      # 镜像
      ImageId: centos_7
      # 实例类型
      InstanceType:
        Ref: EcsInstanceType
      Password:
        Ref: InstancePassword
      AllocatePublicIP:
        Ref: AllocatePublicIp
      InternetMaxBandwidthOut:
        Fn::If:
          - IfAllocatePublicIp
          - Ref: InternetMaxBandwidthOut
          - 0
      InternetChargeType:
        Ref: InternetChargeType
      # 启动脚本
      # 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/bash
            # 挂盘到/data
            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 -t ext4 /dev/vdb1
            cp /etc/fstab /etc/fstab.bak
            mkdir /data
            echo `blkid /dev/vdb1 | awk '{print $2}' | sed 's/\\\"//g'` /data ext4 defaults 0 0 >> /etc/fstab
            mount -a

            mkdir /data/redis
            mkdir /data/redis/logs
            mkdir /data/redis/data
            chown -R redis:redis /data/redis
            sed -i 's/dir .\//dir \/data\/redis\/data/' /etc/redis.conf
            sed -i 's/logfile ""/logfile \/data\/redis\/logs\/redis.log/g' /etc/redis.conf
            sed -i 's/# requirepass foobared/requirepass ${RedisPassword}/g' /etc/redis.conf
            sed -i 's/daemonize no/daemonize yes/g' /etc/redis.conf
            # 这里配置安装脚本

            cat >> /usr/lib/systemd/system/redis.service << "EOF"
            [Unit]
            Description=redis
            After=network.target

            [Service]
            Type=forking
            PIDFile=/var/run/redis_6379.pid
            ExecStart=/usr/bin/redis-server /etc/redis.conf
            ExecStop=/usr/bin/redis-cli shutdown
            PrivateTmp=true

            [Install]
            WantedBy=multi-user.target
            EOF

            systemctl daemon-reload

            # 配置启动脚本
            systemctl enable redis
            systemctl start redis

            # 执行成功回调WaitCondition结束waitCondition的等待
            ${CurlCli} -d "{\"Data\" : \"Success\", \"status\" : \"SUCCESS\"}"
          # 获取到waitConditionHandle的地址放到 ${CurlCli}变量里
          - CurlCli:
              Fn::GetAtt:
                - WaitConditionHandle
                - CurlCli
            RegionId:
              Ref: ALIYUN::Region
            RedisPassword:
              Ref: RedisPassword
# 定义输出
Outputs:
  # 将内网ip做为http返回的地址显示在控制台
  PrivateEndpoint:
    Description:
      zh-cn: 内网IP地址
      en: Private IP Addresses
    Value:
      Fn::Sub:
        - redis://${ServerAddress}:6379
        - ServerAddress:
            Fn::Select:
              - 0
              - Fn::GetAtt:
                 - EcsInstanceGroup
                 - PrivateIps
  # 将公网ip做为http返回的地址显示在控制台
  PublicEndpoint:
    Condition: IfAllocatePublicIp
    Description:
      zh-cn: 对外暴露的公网IP地址
      en: Public IP Addresses
    Value:
      Fn::Sub:
        - redis://${ServerAddress}:6379
        - ServerAddress:
            Fn::Select:
              - 0
              - Fn::GetAtt:
                  - EcsInstanceGroup
                  - PublicIps
  InstallPath:
    Description:
      zh-cn: 安装路径
      en: Install Path
    Value: /opt/redis
Metadata:
  ALIYUN::ROS::Interface:
    # 分组信息
    ParameterGroups:
      - Parameters:
          - PayType
          - PayPeriodUnit
          - PayPeriod
        Label:
          default:
            en: PayType Configuration
            zh-cn: 付费类型配置
      - Parameters:
          - ZoneId
        Label:
          default:
            zh-cn: 可用区配置
            en: Zone Configuration
      - Parameters:
          - VpcId
          - VSwitchId
          - AutoCreateSecurityGroup
          - SecurityGroupId
        Label:
          default:
            zh-cn: 选择已有基础资源配置
            en: Choose existing Infrastructure Configuration
      - Parameters:
          - EcsInstanceType
          - SystemDiskSize
          - DataDiskSize
          - InstancePassword
        Label:
          default:
            en: Instance Configuration
            zh-cn: ECS实例配置
      - Parameters:
          - AllocatePublicIp
          - InternetChargeType
          - InternetMaxBandwidthOut
        Label:
          default:
            en: Network Configurate
            zh-cn: ECS网络配置
      - Parameters:
          - RedisPassword
        Label:
          default:
            en: Redis Configuration
            zh-cn: Redis配置