name: Cloudsoft Web-EFS Exercise 2-1

brooklyn.parameters:
  - name: demo_name
    default: cloudsoft-web-efs-demo
    constraints:
      - regex: '[A-Za-z0-9_-]{1,25}'
    pinned: true
  - name: bucket_name
    constraints:
      - required
      - regex: '[A-Za-z0-9_-]+'

services:
  - type: cloudsoft-web-efs-exercise-web-tier
    id: cloudsoft-web-efs-exercise-web-tier
    name: Web Tier
    brooklyn.config:
      bucket_name: $brooklyn:parent().config("bucket_name")
      demo_name: $brooklyn:parent().config("demo_name")
      vpc: $brooklyn:entity("cloudsoft-web-efs-exercise-efs-tier").attributeWhenReady("tf.output.efs_vpc_id")
      subnets: $brooklyn:entity("cloudsoft-web-efs-exercise-efs-tier").attributeWhenReady("tf.output.efs_subnets")
      web_extra_security_groups: [ $brooklyn:entity("cloudsoft-web-efs-exercise-efs-tier").attributeWhenReady("tf.output.efs_access_security_group") ]
      efs_dns: $brooklyn:entity("cloudsoft-web-efs-exercise-efs-tier").attributeWhenReady("tf.output.efs_access_mount_dns_name")

  - type: cloudsoft-web-efs-exercise-efs-tier
    id: cloudsoft-web-efs-exercise-efs-tier
    name: EFS Tier
    brooklyn.config:
      bucket_name: $brooklyn:parent().config("bucket_name")
      demo_name: $brooklyn:parent().config("demo_name")

  - name: EFS Content Manager
    type: org.apache.brooklyn.entity.stock.BasicEntity
    brooklyn.parameters:
      - name: efs-tier-entity
        type: org.apache.brooklyn.api.entity.Entity
        constraints:
          - required

      - name: source-repo-url
        type: string
        description: The git URL for the repo containing the content to be serverd
        reconfigurable: true
        default: https://github.com/cloudsoft/hello-world-html.git
        constraints:
          - required

      - name: source-committish
        type: string
        reconfigurable: true
        description: >
          The git "committish" (branch or tag or SHA id) within the repo for the version of the content to be served.
          If a branch is used, it will take the latest on the branch.

    brooklyn.config:
      efs-tier-entity: $brooklyn:entity("cloudsoft-web-efs-exercise-efs-tier")

    brooklyn.policies:
      - type: workflow-policy
        brooklyn.config:
          name: Update Files when Bastion Server is up
          triggers:
            # run as soon as the group has a member
            - entity: efs-bastion-server-grouped
              sensor: service.isUp
          steps:
            - invoke-effector updateFiles
      - type: cron-scheduler
        brooklyn.config:
          entries:
            - when: '0 */5 * * * *'
              effector: computeContentCurrentHash

    brooklyn.initializers:
      - type: workflow-effector
        brooklyn.config:
          name: updateFiles

          steps:
            - step: invoke-effector runCommandOnBastionServer
              entity: $brooklyn:config("efs-tier-entity")
              args:
                script: |
                  set -e
                  cd /mnt/shared-file-system
                  
                  export UPDATE_DIR=update-$(date +%s%N)
                  echo Checking out $REPO $COMMITTISH to temporary working dir $UPDATE_DIR
                  mkdir -p $UPDATE_DIR
                  cd $UPDATE_DIR
                  git clone $REPO .
                  if [ ! -z "$COMMITTISH" ] ; then git checkout $COMMITTISH ; fi
                  rm -rf .git
                  echo Checked out, pre-computing hash
                  find . -type f | LC_COLLATE=C sort | xargs md5sum
                  export SOURCE_HASH=$(find . -type f | LC_COLLATE=C sort | xargs md5sum | md5sum | sed 's/ .*//')
                  echo Overall hash is $SOURCE_HASH
                  cd ..
                  
                  export TRASH_DIR=trash-$(date +%s%N)
                  if [ -d active ] ; then
                    echo Moving previous active dir to $TRASH_DIR
                    mv active $TRASH_DIR
                  fi
                  
                  mv $UPDATE_DIR active
                  echo Moved updated dir into active
                  
                  if [ -f $TRASH_DIR ] ; then
                    echo Deleting previous active dir now in $TRASH_DIR
                    rm -rf $TRASH_DIR
                  fi
                  
                  echo ---
                  echo $SOURCE_HASH

                env:
                  REPO: $brooklyn:config("source-repo-url")
                  COMMITTISH: $brooklyn:config("source-committish")

                on-error:
                  - return last installed hash unavailable

            - transform out = ${stdout} | yaml
            - set-sensor string content-last-installed-hash = ${out}
            - invoke-effector computeContentCurrentHash
            - return ${out}

      - type: workflow-effector
        brooklyn.config:
          name: computeContentCurrentHash

          steps:
            - step: invoke-effector runCommandOnBastionServer
              entity: $brooklyn:config("efs-tier-entity")
              args:
                script: |
                  cd /mnt/shared-file-system/active
                  echo md5sum on all files and overall stdin
                  find . -type f | LC_COLLATE=C sort | xargs md5sum
                  echo ---
                  find . -type f | LC_COLLATE=C sort | xargs md5sum | md5sum | sed 's/ .*//'
            - transform out = ${stdout} | yaml
            - set-sensor string content-current-hash = ${out}
            - return ${out}

      - type: workflow-sensor
        brooklyn.config:
          sensor:
            name: source-current-hash
          period: 2m    # every 2 minutes is quite often for production but useful for an exercise
          steps:
            - step: container cloudsoft/terraform   # not using terraform, but this has git pre-installed
              env:
                REPO: $brooklyn:config("source-repo-url")
                COMMITTISH: $brooklyn:config("source-committish")
              command: |
                export WORKING_DIR=check-expected-$(date +%s%N)
                echo Checking out $REPO $COMMITTISH to temporary working dir $WORKING_DIR
                cd /tmp
                mkdir -p $WORKING_DIR
                cd $WORKING_DIR
                git clone $REPO .
                git checkout $COMMITTISH
                rm -rf .git
                echo md5sum on all files and overall stdin
                find . -type f | LC_COLLATE=C sort | xargs md5sum
                SOURCE_CURRENT_HASH=$(find . -type f | LC_COLLATE=C sort | xargs md5sum | md5sum | sed 's/ .*//')
                cd ..
                rm -rf $WORKING_DIR
                echo ---
                echo $SOURCE_CURRENT_HASH
              on-error:
                - return current hash unavailable
            - transform out = ${stdout} | yaml
            - return ${out}

      - type: workflow-sensor
        brooklyn.config:
          sensor:
            name: dashboard.compliance.content-unmodified
            type: compliance-check
          triggers:
            - content-current-hash
            - content-last-installed-hash
          steps:
            - step: container ubuntu:latest
              env:
                CONTENT_CURRENT_HASH: ${entity.sensor['content-current-hash']}
                SOURCE_LAST_INSTALLED_HASH: ${entity.sensor['content-last-installed-hash']}
                ENTITY_ID: $brooklyn:entityId()
              command: |
                cat << EOF
                  id: $ENTITY_ID:check-file-system-content-matches-last-installed
                EOF
                if [ "$CONTENT_CURRENT_HASH" == "$SOURCE_LAST_INSTALLED_HASH" ] ; then
                  cat << EOF
                  summary: Shared filesystem content matches what was installed
                  pass:    true
                EOF
                else 
                  cat << EOF
                  summary: Shared filesystem content has CHANGED ON DISK since installation
                  pass:    false
                  notes: |2
                    Hash code of content when installed was: $SOURCE_LAST_INSTALLED_HASH
                    Hash code of current content is:         $CONTENT_CURRENT_HASH
                EOF
                fi
              on-error:
                - 'return { summary: Data unavailable, pass: false }'
            - transform out = ${stdout} | yaml | type compliance-check
            - return ${out}

      - type: workflow-sensor
        brooklyn.config:
          sensor:
            name: dashboard.compliance.content-current
            type: compliance-check
          triggers:
            - content-current-hash
            - source-current-hash
          steps:
            - step: container ubuntu:latest
              env:
                CONTENT_CURRENT_HASH: ${entity.sensor['content-current-hash']}
                SOURCE_CURRENT_HASH: ${entity.sensor['source-current-hash']}
                ENTITY_ID: $brooklyn:entityId()
              command: |
                cat << EOF
                  id: $ENTITY_ID:check-file-system-content-matches-current-source-control
                EOF
                if [ "$CONTENT_CURRENT_HASH" == "$SOURCE_CURRENT_HASH" ] ; then
                  cat << EOF
                  summary: Shared filesystem content is up-to-date with source control
                  pass:    true
                EOF
                else 
                  cat << EOF
                  summary: Shared filesystem content is DIFFERENT to current source control
                  notes: |2
                    Hash code of current content is:         $CONTENT_CURRENT_HASH
                    Hash code of latest source control code: $SOURCE_CURRENT_HASH
                    
                    Check whether there are new commits to source control and consider installing them.
                
                  pass: false
                EOF
                fi
              on-error:
                - 'return { summary: Data unavailable, pass: false }'
            - transform out = ${stdout} | yaml | type compliance-check
            - return ${out}

brooklyn.enrichers:
  - type: org.apache.brooklyn.enricher.stock.Propagator
    brooklyn.config:
      producer: $brooklyn:entity("cloudsoft-web-efs-exercise-web-tier")
      propagating:
        - main.uri

