#  Licensed under the Apache License, Version 2.0 (the "License"); you may
#  not use this file except in compliance with the License. You may obtain
#  a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#  License for the specific language governing permissions and limitations
#  under the License.

Namespaces:
  =: io.murano.system
  std: io.murano

Name: AwsSecurityGroupManager

Extends: SecurityGroupManager

Methods:
  .init:
    Body:
      - $._environment: $.find(std:Environment)
      - $._region: $.find(std:CloudRegion).require()

  addGroupIngress:
    Arguments:
      - rules:
          Contract:
            - FromPort: $.int().notNull()
              ToPort: $.int().notNull()
              IpProtocol: $.string().notNull()
              External: $.bool().notNull()
              Ethertype: $.string().check($ in list(null, 'IPv4', 'IPv6'))
      - groupName:
          Contract: $.string().notNull()
          Default: $this.defaultGroupName
    Body:
      - $._addGroup(ingress, $rules, $groupName)

  addGroupEgress:
    Arguments:
      - rules:
          Contract:
            - FromPort: $.int().notNull()
              ToPort: $.int().notNull()
              IpProtocol: $.string().notNull()
              External: $.bool().notNull()
              Ethertype: $.string().check($ in list(null, 'IPv4', 'IPv6'))
      - groupName:
          Contract: $.string().notNull()
          Default: $this.defaultGroupName
    Body:
      - $._addGroup(egress, $rules, $groupName)

  _addGroup:
    Arguments:
      - direction:
          Contract: $.string().notNull().check($ in list(ingress, egress))
          Default: ingress
      - rules:
          Contract:
            - FromPort: $.int().notNull()
              ToPort: $.int().notNull()
              IpProtocol: $.string().notNull()
              External: $.bool().notNull()
              Ethertype: $.string().check($ in list(null, 'IPv4', 'IPv6'))
      - groupName:
          Contract: $.string().notNull()
          Default: $this.defaultGroupName
    Body:
      - $ext_keys:
          true:
            ext_key: remote_ip_prefix
            ext_val: '0.0.0.0/0'
          false:
            ext_key: remote_mode
            ext_val: remote_group_id

      - $ethertype: $rules.where($.get(Ethertype) = IPv6)
      - If: len($ethertype) > 0
        Then:
          - $msg: 'Unable to add security group. IPv6 is not supported.'
          - $._environment.reporter.report_error($this, $msg)
          - Throw: UnsupportedPropertyValue
            Message: $msg
      - $groupDirection: dict(egress => SecurityGroupEgress).get($direction, SecurityGroupIngress)

      - $stack: $._region.stack
      - $template:
          resources:
            $groupName:
              type: 'AWS::EC2::SecurityGroup'
              properties:
                GroupDescription: format('Composite security group of Murano environment {0}', $._environment.name)
                $groupDirection:
                  - FromPort: '-1'
                    ToPort: '-1'
                    IpProtocol: icmp
                    CidrIp: '0.0.0.0/0'
      - $._region.stack.updateTemplate($template)

      - $rulesList: $rules.select(dict(
            FromPort => str($.FromPort),
            ToPort => str($.ToPort),
            IpProtocol => $.IpProtocol,
            CidrIp => '0.0.0.0/0'
          ))

      - $template:
          resources:
            $groupName:
              type: 'AWS::EC2::SecurityGroup'
              properties:
                $groupDirection: $rulesList
      - $._region.stack.updateTemplate($template)
