# Usage:
# heat -v stack-create $YOUR_STACK_NAME \
# --template-file /path/to/grafana.template \
# -P rax_tenant=$RAX_TENANT_ID \
# -P rax_username=$RAX_USER_NAME \
# -P rax_apikey=$RAX_API_KEY
# -P host_name=$WHAT_YOU_WANT_TO_CALL_IT
#
# What to expect:
# A Cloud Server with a self-contained Grafana 3.1.1 installation that serves metrics
# from the Rackspace Cloud Metrics API. A default dashboard will be configured
# to serve metrics from the server you spin up.
#
# Grafana will be protected with basic authentication, user=grafana, pass=$RANDOM_TEXT.
#
# You may need to request that the Cloud Metrics API endpoints be added to your
# tenant. Contact support@rackspace.com for that.

heat_template_version: 2013-05-23

description: >
  Puts together a server that will run Grafana 3.1.1 using Cloud Metrics data.

parameter_groups:
  - label: 'Server Settings'
    parameters:
      - flavor
      - image
      - host_name
      - es_version
      - rax_tenant
      - rax_username
      - rax_apikey
  - label: 'Apache Settings'
    parameters:
      - apache_auth_user

parameters:
  image:
    default: 'Ubuntu 14.04 LTS (Trusty Tahr) (PVHVM) (Orchestration)'
    label: 'Operating System'
    type: string
    description: 'Server image that will be used'
    constraints:
      - description: 'supported os versions'
        allowed_values:
          - 'Ubuntu 14.04 LTS (Trusty Tahr) (PVHVM) (Orchestration)'
  flavor:
    default: '2GB Standard Instance'
    label: 'Server Size'
    type: string
    description: 'Cloud Server flavor (size) to use'
    constraints:
      - description: 'supported server sizes. should have at least 2G RAM'
        allowed_values:
          - '2 GB Performance'
          - '4 GB Performance'
          - '8 GB Performance'
          - '15 GB Performance'
          - '30 GB Performance'
          - '2GB Standard Instance'
          - '4GB Standard Instance'
          - '8GB Standard Instance'
          - '15GB Standard Instance'
          - '30GB Standard Instance'
  host_name:
    default: grafana
    type: string
    description: 'Server hostname'
    label: 'Server hostname'
  apache_auth_user:
    default: grafana
    type: string
    description: 'User name used to authenticate into Apache (which serves Grafana).'
    label: 'Username'
  es_version:
    default: '1.3.4'
    type: string
    description: 'Elasticsearch version'
    label: 'Elasticsearch version'
  rax_tenant:
    default: 'notavalidtenantdkw93ddkwl'
    type: string
    description: 'Rackspace tenant ID'
    label: 'tenant ID'
  rax_username:
    default: 'notavaliduserskldk2e'
    type: string
    description: 'Rackspace user name'
    label: 'username'
  rax_apikey:
    default: 'notavalidapikeykslkdjlkj2'
    type: string
    description: 'Rackspace account API key'
    label: 'API key'

outputs:
  private_key:
    description: 'SSH private key'
    value: { get_attr: [ssh_key, private_key ] }
  apache_auth_user:
    description: 'Grafana auth user.'
    value:
      get_param: apache_auth_user
  apache_auth_password:
    description: 'Grafana auth password.'
    value: { get_attr: [apache_auth_password, value ] }
  public_ip:
    description: IP Address
    value: { get_attr: [cloud_server, accessIPv4] }

resources:
  cloud_server:
    type: OS::Nova::Server
    depends_on: [ apache_auth_password ]
    properties:
      key_name: { get_resource: ssh_key }
      flavor: { get_param: flavor }
      name: { get_param: [host_name, value] }
      image: { get_param: image }
      user_data_format: SOFTWARE_CONFIG
      config_drive: true
      software_config_transport: POLL_TEMP_URL
      metadata:
        rax-heat: { get_param: "OS::stack_id" }

  grafana_config:
    type: OS::Heat::SoftwareConfig
    properties:
      group: script
      config:
        str_replace:
          template: |
            #!/bin/bash -x
            exec 2>&1
            exec 1>/tmp/bash-debug.log

            ps auxwwef
            sleep 120
            echo after sleep
            ps auxwwef
            rm -f /var/lib/dpkg/lock

            export DEBIAN_FRONTEND=noninteractive
            echo debconf shared/accepted-oracle-license-v1-1 select true | debconf-set-selections
            echo debconf shared/accepted-oracle-license-v1-1 seen true | debconf-set-selections
            add-apt-repository -y ppa:webupd8team/java
            apt-get update -y --force-yes
            sleep 5
            echo installing packages now, one at a time.
            for i in wget oracle-java7-installer vim git nginx nginx-extras apache2-utils python-dev python-setuptools python-pip build-essential libcairo2-dev libffi-dev python-virtualenv python-dateutil ; do
              echo installing "$i"
              apt-get install -y $i --force-yes 2>&1 | tee /tmp/$i.install.log
            done

            curl -o /tmp/elasticsearch-es_version.deb https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-es_version.deb
            dpkg -i /tmp/elasticsearch-es_version.deb
            update-rc.d elasticsearch defaults 95 10
            mv /etc/elasticsearch/elasticsearch.yml /etc/elasticsearch/elasticsearch-default.yml
            echo cluster.name: es_grafana > /etc/elasticsearch/elasticsearch.yml
            echo network.host: 127.0.0.1 >> /etc/elasticsearch/elasticsearch.yml
            /etc/init.d/elasticsearch start

            wget https://grafanarel.s3.amazonaws.com/builds/grafana_3.1.1-1470047149_amd64.deb
            apt-get install -y adduser libfontconfig
            dpkg -i grafana_3.1.1-1470047149_amd64.deb
            service grafana-server start
            sleep 5
            grafana-cli plugins install rackerlabs-blueflood-datasource
            sed -i '/allow_sign_up = true/c\allow_sign_up = false' /usr/share/grafana/conf/defaults.ini
            service grafana-server restart

            rm /etc/nginx/sites-enabled/default
            export heat_one_parameter='$1'
            export heat_host_parameter='$host'
            cat > /etc/nginx/sites-available/grafana << EOL
            upstream graphite {
              server 127.0.0.1:8888;
            }
            upstream elasticsearch {
              server 127.0.0.1:9200;
            }
            server {
              listen 80;
              location /graphite/ {
                rewrite /graphite/(.*) /$heat_one_parameter break;
                proxy_pass http://graphite;
                proxy_redirect off;
                proxy_set_header Host $heat_host_parameter;
              }
              location /elasticsearch/ {
                rewrite /elasticsearch/(.*) /$heat_one_parameter break;
                proxy_pass http://elasticsearch;
                proxy_redirect off;
                proxy_set_header Host $heat_host_parameter;
              }
              location / {
                proxy_pass http://localhost:3000/;
                proxy_redirect off;
                proxy_set_header Host $heat_host_parameter;
              }
            }
            EOL

            ln -s /etc/nginx/sites-available/grafana /etc/nginx/sites-enabled/grafana
            /etc/init.d/nginx restart
            pip install gunicorn
            pip install --upgrade "git+http://github.com/rackerlabs/graphite-api.git@1.1.3-rax.1"
            pip install --upgrade blueflood-graphite-finder
            cat > /etc/graphite-api.yaml << EOL
            search_index: /dev/null
            finders:
              - blueflood_graphite_finder.blueflood.TenantBluefloodFinder
            functions:
              - graphite_api.functions.SeriesFunctions
              - graphite_api.functions.PieFunctions
            time_zone: UTC
            blueflood:
              tenant: rax_tenant
              username: rax_username
              apikey: rax_apikey
              authentication_module: blueflood_graphite_finder.rax_auth
              authentication_class: BluefloodAuth
              urls:
                - http://iad.metrics.api.rackspacecloud.com
            logging:
              version: 1
              handlers:
                blueflood_finder_loghandler:
                  class: logging.handlers.RotatingFileHandler
                  filename: /var/log/blueflood-graphite-finder.log
                  formatter: default
                  backupCount: 2
                  maxBytes: 536870912
              loggers:
                blueflood_finder:
                  handlers:
                    - blueflood_finder_loghandler
                  propagate: true
                  level: INFO
              formatters:
                default:
                  format: '%(asctime)s %(levelname)-8s %(name)-15s %(message)s'
                  datefmt: '%Y-%m-%d %H:%M:%S'
            EOL

            echo rax_tenant > ~/tenant_id
            cat > /etc/init/graphite-api.conf << EOL
            description "Graphite-API server"
            start on runlevel [2345]
            stop on runlevel [!2345]
            console log
            respawn
            exec gunicorn -b 127.0.0.1:8888 --access-logfile /var/log/gunicorn-access.log --error-logfile /var/log/gunicorn-error.log -w 8 graphite_api.app:app
            EOL

            cat > /root/.raxrc << EOL
            [credentials]
            username=rax_username
            api_key=rax_apikey
            [api]
            url=https://monitoring.api.rackspacecloud.com/v1.0
            EOL

            start graphite-api
            curl -i -H "Content-Type: application/json" -X POST 'http://admin:admin@localhost/api/datasources' -d \
            '{
              "name":"blueflood",
              "type":"rackerlabs-blueflood-datasource",
              "url":"http://localhost:8888",
              "access":"proxy",
              "basicAuth":false,
              "withCredentials":false,
              "isDefault":true
            }'
            curl -i -H "Content-Type: application/json" -X PUT 'http://admin:admin@localhost/api/users/1' -d '{ "login": "apache_auth_user" }'
            curl -i -H "Content-Type: application/json" -X PUT 'http://apache_auth_user:admin@localhost/api/admin/users/1/password' -d '{ "password": "apache_auth_password" }'

            ufw enable
            ufw allow ssh
            ufw allow http
            ufw allow https

          params:
            es_version: { get_param: es_version }
            apache_auth_user: { get_param: apache_auth_user }
            apache_auth_password: { get_attr: [apache_auth_password, value ] }
            rax_tenant: { get_param: rax_tenant }
            rax_username: { get_param: rax_username }
            rax_apikey: { get_param: rax_apikey }

  grafana_deploy:
    type: OS::Heat::SoftwareDeployment
    properties:
      signal_transport: TEMP_URL_SIGNAL
      config: { get_resource: grafana_config }
      server: { get_resource: cloud_server }

  ssh_key:
    type: 'OS::Nova::KeyPair'
    properties:
      name:
        get_param: 'OS::stack_id'
      save_private_key: true

  apache_auth_password:
    type: 'OS::Heat::RandomString'
    properties:
      length: 16
      sequence: lettersdigits