name: EFS with Bastion Server with Sensors and Effectors

brooklyn.parameters:
  - name: demo_name
    default: cloudsoft-amp-efs-exercise
    constraints:
      - regex: '[A-Za-z0-9_-]+'
    pinned: true

  - name: bucket_name
    constraints:
      - required
      - regex: '[A-Za-z0-9_-]+'

brooklyn.config:
  tf_var.name:                   $brooklyn:config("demo_name")
  shell.env:
    AWS_ACCESS_KEY_ID:           $brooklyn:external("exercise-secrets", "aws-access-key-id")
    AWS_SECRET_ACCESS_KEY:       $brooklyn:external("exercise-secrets", "aws-secret-access-key")
  tf.extra.templates.contents:
    backend.tf: |
      terraform {
        backend "s3" {
          bucket = "${config.bucket_name}"
          key    = "${config.demo_name}/${name}"
          region = "eu-west-1"
        }
      }
  
services:

  - name:                        EFS Volume
    type:                        terraform
    id:                          efs-volume
    brooklyn.config:
      tf.configuration.url:      https://docs.cloudsoft.io/tutorials/exercises/3-efs-terraform-deep-dive/3-1/efs-volume-tf.zip

    brooklyn.children:
      - type: org.apache.brooklyn.entity.group.DynamicGroup
        name: EFS Volume (Grouped)
        id: efs-volume-grouped
        brooklyn.config:
          dynamicgroup.entityfilter:
            config: tf.resource.address
            equals: aws_efs_file_system.main
        brooklyn.policies:
          - type: org.apache.brooklyn.entity.group.GroupsChangePolicy
            brooklyn.config:
              member.initializers:
                - type: workflow-sensor
                  brooklyn.config:
                    sensor:
                      name: efs-size-from-aws
                      type: integer
                    triggers:
                      - tf.value.size_in_bytes
                    steps:
                      - transform size_json = ${entity.sensor['tf.value.size_in_bytes']} | bash
                      - container stedolan/jq echo ${size_json} | jq '.[0].value'
                      - return ${stdout}
                    on-error:
                      - clear-sensor efs-size-from-aws
        brooklyn.enrichers:
          - type: org.apache.brooklyn.enricher.stock.Aggregator
            brooklyn.config:
              enricher.sourceSensor: efs-size-from-aws
              enricher.targetSensor: efs-size-from-aws
              transformation: first  # list, sum, min, max, average

  - name:                        Bastion Server for accessing EFS
    type:                        terraform
    id:                          efs-bastion-server
    brooklyn.config:
      tf.configuration.url:      https://docs.cloudsoft.io/tutorials/exercises/3-efs-terraform-deep-dive/3-1/efs-server-tf.zip
      tf_var.subnet:             $brooklyn:entity("efs-volume").attributeWhenReady("tf.output.efs_access_subnet")
      tf_var.efs_security_group: $brooklyn:entity("efs-volume").attributeWhenReady("tf.output.efs_access_security_group")
      tf_var.efs_mount_dns_name: $brooklyn:entity("efs-volume").attributeWhenReady("tf.output.efs_access_mount_dns_name")
      tf_var.ami_user:           ec2-user

    brooklyn.children:
      - type: org.apache.brooklyn.entity.group.DynamicGroup
        name: EFS Bastion Server (Grouped)
        id: efs-bastion-server-grouped
        brooklyn.config:
          dynamicgroup.entityfilter:
            config: tf.resource.address
            equals: aws_instance.efs_bastion
        brooklyn.policies:
          - type: org.apache.brooklyn.entity.group.GroupsChangePolicy
            brooklyn.config:
              member.locations:
                - type: org.apache.brooklyn.location.ssh.SshMachineLocation
                  brooklyn.config:
                    user: $brooklyn:config("tf_var.ami_user")
                    address: $brooklyn:parent().attributeWhenReady("tf.output.efs_bastion_server_ip")
                    privateKeyData: $brooklyn:parent().attributeWhenReady("tf.output.efs_bastion_server_private_key")
              member.initializers:
                - type: workflow-sensor
                  brooklyn.config:
                    sensor:
                      name: efs-size-from-server
                      type: integer
                    period: 2m
                    steps:
                      - ssh du --block-size=4096 /mnt/shared-file-system | tail -1 | awk '{print $1 * 4096}'
                      - let result = ${stdout}
                      - ssh date > /tmp/cloudsoft-amp-efs-size-from-server.last-date
                      - return ${result}
                - type: workflow-effector
                  brooklyn.config:
                    name: authorizeSshKey
                    parameters:
                      PUBLIC_SSH_KEY:
                        description: SSH key (public part) to authorize on this machine
                    steps:
                      - ssh echo ${PUBLIC_SSH_KEY} >> ~/.ssh/authorized_keys
        brooklyn.enrichers:
          - type: org.apache.brooklyn.enricher.stock.Aggregator
            brooklyn.config:
              enricher.sourceSensor: efs-size-from-server
              enricher.targetSensor: efs-size-from-server
              transformation: first

brooklyn.enrichers:
  - type: org.apache.brooklyn.enricher.stock.Propagator
    brooklyn.config:
      producer: $brooklyn:entity("efs-volume-grouped")
      propagating:
        - efs-size-from-aws

  - type: org.apache.brooklyn.enricher.stock.Propagator
    brooklyn.config:
      producer: $brooklyn:entity("efs-volume")
      propagating:
        - tf.output.efs_access_mount_dns_name

  - type: org.apache.brooklyn.enricher.stock.Propagator
    brooklyn.config:
      producer: $brooklyn:entity("efs-bastion-server-grouped")
      propagating:
        - efs-size-from-server

  - type: org.apache.brooklyn.enricher.stock.Propagator
    brooklyn.config:
      producer: $brooklyn:entity("efs-bastion-server")
      propagating:
        - tf.output.efs_bastion_server_ip
