#cloud-config
write_files:
  - path: "/etc/teamcity/update.sh"
    permissions: 0755
    content: |
      #!/bin/bash
      while true
      do
        STATUS=$(curl -s -o /etc/teamcity/tags -w '%{http_code}' -H Metadata:true "http://169.254.169.254/metadata/instance/compute/tags?api-version=2017-08-01&format=text")
        if [ $STATUS -eq 200 ]; then
          VERSION=$(cat /etc/teamcity/tags | sed -n 's/.*teamcity-version\:\([^;]\+\).*/\1/p')
          if [[ ! -z "$VERSION" ]]; then
            TEAMCITY_VERSION="TEAMCITY_VERSION=$VERSION"
            CURRENT_VERSION=$(at /etc/teamcity/version)
            if [ "$TEAMCITY_VERSION" != "$CURRENT_VERSION" ]; then
                echo "TeamCity version has changed to $VERSION"
                echo "$TEAMCITY_VERSION" > /etc/teamcity/version
                /usr/bin/docker pull jetbrains/teamcity-server:${VERSION}
                /usr/bin/docker pull jetbrains/teamcity-agent:${VERSION}
            fi
          fi
        fi
        sleep 60
      done
  - path: "/etc/teamcity/database.properties"
    content: |
      # Database: MySQL

      connectionUrl=jdbc:mysql://%RDSHost%/%RDSDataBase%?useSSL=true&requireSSL=false
      connectionProperties.user=teamcity@%RDSHost%
      connectionProperties.password=%RDSPassword%

      maxConnections=50
      testOnBorrow=true
  - path: "/etc/teamcity/disabled-plugins.xml"
    content: |
      <?xml version="1.0" encoding="UTF-8"?>
      <disabled-plugins>
        <disabled-plugin name="cloud-amazon" />
        <disabled-plugin name="s3-artifact-storage" />
        <disabled-plugin name="vsphere" />
      </disabled-plugins>
  - path: "/etc/teamcity/hostname"
    content: |
      DOMAIN_NAME=%DomainName%
  - path: "/etc/teamcity/check-certificate.sh"
    permissions: 0755
    content: |
      #!/bin/bash
      attempt=0
      while docker exec letsencrypt /app/cert_status | grep ${DOMAIN_NAME} > /dev/null; [[ $? -ne 0 ]]; do
        retry_in_mins=$((3**$attempt))
        echo "Will try to renew certificate for ${DOMAIN_NAME} in $retry_in_mins minutes"
        sleep $((60 * $retry_in_mins))
        echo "Trying to renew certificate for ${DOMAIN_NAME}..."
        docker exec letsencrypt /app/signal_le_service
        sleep 30
        attempt=$(($attempt + 1))
      done
  - path: "/etc/teamcity/download-file.sh"
    permissions: 0755
    content: |
      #!/bin/bash
      attempt=0
      until $(curl --output $2 --silent --fail $1); do
        retry_in_secs=$((3**$attempt))
        echo "Will try to download file $1 in $retry_in_secs minutes"
        sleep $retry_in_secs
        echo "Trying to download file $1..."
        attempt=$(($attempt + 1))
      done
  - path: "/etc/flatcar/update.conf"
    content: |
      REBOOT_STRATEGY="off"
flatcar:
  units:
    - name: "format-mnt-data.service"
      enable: true
      content: |
        [Unit]
        Requires=network-online.target
        Before=teamcity-server.service mnt-data.mount
        RequiresMountsFor=/dev/mapper
        ConditionPathExists=!/dev/mapper/app-data

        [Service]
        Type=oneshot
        ExecStart=/bin/bash -c \
          '/usr/sbin/pvcreate /dev/disk/azure/scsi1/lun0 && \
          /usr/sbin/vgcreate app /dev/disk/azure/scsi1/lun0 && \
          /usr/sbin/lvcreate -l 100%%FREE -n data app && \
          /usr/sbin/mkfs.ext4 /dev/mapper/app-data'

        [Install]
        WantedBy=multi-user.target
    - name: "mnt-data.mount"
      enable: true
      content: |
        [Unit]
        Before=teamcity-server.service
        After=format-mnt-data.service
        Requires=format-mnt-data.service
        ConditionVirtualization=!container
        Conflicts=umount.target
        [Mount]
        What=/dev/mapper/app-data
        Where=/mnt/data
        Type=ext4
        Options=
        [Install]
        RequiredBy=teamcity-server.service
    - name: "get-mysql-connector.service"
      enable: true
      content: |
        [Unit]
        Before=teamcity-server.service
        After=mnt-data.mount
        Requires=mnt-data.mount
        ConditionPathExists=!/mnt/data/teamcity-server/data/lib/jdbc/mysql-connector-java-bin.jar

        [Service]
        Type=oneshot
        ExecStart=/bin/mkdir -p /mnt/data/teamcity-server/data/lib/jdbc
        ExecStart=/bin/bash /etc/teamcity/download-file.sh \
          https://repo.maven.apache.org/maven2/mysql/mysql-connector-java/5.1.47/mysql-connector-java-5.1.47.jar \
          /mnt/data/teamcity-server/data/lib/jdbc/mysql-connector-java-bin.jar

        [Install]
        WantedBy=multi-user.target
    - name: "get-azure-plugins.service"
      enable: true
      content: |
        [Unit]
        Before=teamcity-server.service
        After=mnt-data.mount
        Requires=mnt-data.mount
        ConditionPathExists=!/mnt/data/teamcity-server/data/plugins/azure-plugins.txt

        [Service]
        Type=oneshot
        ExecStart=/bin/mkdir -p /mnt/data/teamcity-server/data/plugins
        ExecStart=/bin/bash /etc/teamcity/download-file.sh \
          https://raw.githubusercontent.com/JetBrains/teamcity-azure-template/master/azure-plugins.txt \
          /mnt/data/teamcity-server/data/plugins/azure-plugins.txt
        ExecStart=/bin/bash -c 'cd /mnt/data/teamcity-server/data/plugins && curl -K azure-plugins.txt'

        [Install]
        WantedBy=multi-user.target
    - name: "prepare-config.service"
      enable: true
      content: |
        [Unit]
        Before=teamcity-server.service
        After=mnt-data.mount
        Requires=mnt-data.mount network-online.target
        ConditionPathExists=!/mnt/data/teamcity-server/data/config

        [Service]
        Type=oneshot
        ExecStart=/bin/mkdir -p /mnt/data/teamcity-server/data/config
        ExecStart=/bin/mv /etc/teamcity/database.properties /mnt/data/teamcity-server/data/config/
        ExecStart=/bin/mv /etc/teamcity/disabled-plugins.xml /mnt/data/teamcity-server/data/config/

        [Install]
        WantedBy=multi-user.target
    - name: "teamcity-update.service"
      command: "start"
      content: |
        [Unit]
        After=docker.service
        Before=teamcity-server.service teamcity-agent.service
        Requires=docker.service network-online.target

        [Service]
        ExecStart=/bin/sh /etc/teamcity/update.sh
        Restart=always

        [Install]
        WantedBy=multi-user.target
    - name: "teamcity-server.service"
      command: "start"
      content: |
        [Unit]
        Description=TeamCity Server
        After=docker.service mnt-data.mount get-mysql-connector.service get-azure-plugins.service prepare-config.service teamcity-update.service letsencrypt.service
        Requires=docker.service mnt-data.mount get-mysql-connector.service get-azure-plugins.service prepare-config.service teamcity-update.service letsencrypt.service

        [Service]
        TimeoutStartSec=1200s
        EnvironmentFile=/etc/teamcity/version
        EnvironmentFile=/etc/teamcity/hostname
        ExecStartPre=/bin/sh -c "docker images --filter 'before=jetbrains/teamcity-server:${TEAMCITY_VERSION}' --format '{{.ID}} {{.Repository}}' | grep 'jetbrains/teamcity-server' | grep -Eo '^[^ ]+' | xargs -r docker rmi"
        ExecStartPre=/usr/bin/docker create \
          -e TEAMCITY_SERVER_MEM_OPTS="-Xmx$(($(grep MemTotal /proc/meminfo | awk '{print $2}') / 2))k -XX:MaxPermSize=270m -XX:ReservedCodeCacheSize=350m" \
          -e VIRTUAL_PORT=8111 \
          -e VIRTUAL_HOST=${DOMAIN_NAME} \
          -e LETSENCRYPT_HOST=${DOMAIN_NAME} %DomainOwnerEmailEnv% \
          -v /mnt/data/teamcity-server/data:/data/teamcity_server/datadir \
          -v /mnt/data/teamcity-server/logs:/opt/teamcity/logs \
          -v /mnt/resource/teamcity-server/temp:/opt/teamcity/temp \
          --name teamcity-server \
          jetbrains/teamcity-server:${TEAMCITY_VERSION}
        ExecStartPre=/bin/sh -c "echo 'azure' > dist && docker cp dist teamcity-server:/opt/teamcity/webapps/ROOT/WEB-INF/DistributionType.txt && rm dist"
        ExecStart=/usr/bin/docker start teamcity-server -a
        ExecStop=-/usr/bin/docker exec teamcity-server /opt/teamcity/bin/teamcity-server.sh stop 60
        ExecStopPost=-/usr/bin/docker stop teamcity-server
        ExecStopPost=-/usr/bin/docker rm teamcity-server
        Restart=always

        [Install]
        WantedBy=multi-user.target
    - name: "teamcity-agent.service"
      command: "start"
      content: |
        [Unit]
        Description=TeamCity Agent
        After=teamcity-server.service teamcity-update.service
        Requires=docker.service teamcity-server.service teamcity-update.service

        [Service]
        TimeoutStartSec=1200s
        EnvironmentFile=/etc/teamcity/version
        EnvironmentFile=/etc/teamcity/hostname
        ExecStartPre=/bin/sh -c "docker images --filter 'before=jetbrains/teamcity-agent:${TEAMCITY_VERSION}' --format '{{.ID}} {{.Repository}}' | grep 'jetbrains/teamcity-agent' | grep -Eo '^[^ ]+' | xargs -r docker rmi"
        ExecStart=/usr/bin/docker run \
          -v /mnt/data/teamcity-agent/conf:/opt/buildagent/conf \
          -v /mnt/data/teamcity-agent/logs:/opt/buildagent/logs \
          -v /mnt/data/teamcity-agent/plugins:/opt/buildagent/plugins \
          -v /mnt/data/teamcity-agent/system:/opt/buildagent/system \
          -v /mnt/resource/teamcity-agent/temp:/opt/buildagent/temp \
          -v /mnt/resource/teamcity-server/temp:/opt/teamcity/temp \
          -v /mnt/data/teamcity-agent/tools:/opt/buildagent/tools \
          --privileged \
          -e DOCKER_IN_DOCKER=start \
          -e SERVER_URL=https://${DOMAIN_NAME} \
          -e AGENT_NAME=Default \
          --name teamcity-agent \
          jetbrains/teamcity-agent:${TEAMCITY_VERSION}
        ExecStop=-/usr/bin/docker exec teamcity-agent /opt/buildagent/bin/agent.sh stop
        ExecStopPost=-/usr/bin/docker stop teamcity-agent
        ExecStopPost=-/usr/bin/docker rm teamcity-agent
        Restart=always

        [Install]
        WantedBy=multi-user.target
    - name: "nginx.service"
      command: "start"
      content: |
        [Unit]
        Description=NGINX reverse proxy
        Requires=docker.service

        [Service]
        TimeoutStartSec=1200s
        ExecStartPre=/bin/mkdir -p /opt/domains/certs
        ExecStartPre=/bin/mkdir -p /opt/domains/vhost.d
        ExecStartPre=/bin/mkdir -p /opt/domains/nginx/html
        ExecStart=/usr/bin/docker run \
          -p 80:80 \
          -p 443:443 \
          -v /opt/domains/certs:/etc/nginx/certs:ro \
          -v /opt/domains/vhost.d:/etc/nginx/vhost.d \
          -v /opt/domains/nginx/html:/usr/share/nginx/html \
          -v /var/run/docker.sock:/tmp/docker.sock:ro \
          --name nginx \
          jwilder/nginx-proxy
        ExecStop=-/usr/bin/docker stop nginx
        ExecStopPost=-/usr/bin/docker rm nginx
        Restart=always

        [Install]
        WantedBy=multi-user.target
    - name: "letsencrypt.service"
      command: "start"
      content: |
        [Unit]
        Description=Let's Encrypt
        Requires=docker.service nginx.service
        After=nginx.service

        [Service]
        TimeoutStartSec=1200s
        ExecStart=/usr/bin/docker run \
          -v /opt/domains/certs:/etc/nginx/certs:rw \
          --volumes-from nginx \
          -v /var/run/docker.sock:/var/run/docker.sock:ro \
          --name letsencrypt \
          jrcs/letsencrypt-nginx-proxy-companion
        ExecStop=-/usr/bin/docker stop letsencrypt
        ExecStopPost=-/usr/bin/docker rm letsencrypt
        Restart=always

        [Install]
        WantedBy=multi-user.target
    - name: "report-waiter-status.service"
      enable: true
      command: "start"
      content: |
        [Unit]
        Requires=docker.service teamcity-server.service nginx.service letsencrypt.service
        ConditionPathExists=!/etc/teamcity/waiter

        [Service]
        Type=oneshot
        EnvironmentFile=/etc/teamcity/hostname
        ExecStartPre=/bin/bash /etc/teamcity/check-certificate.sh
        ExecStart=/bin/bash -c "until $(curl --output /dev/null --silent --fail https://${DOMAIN_NAME}); do echo 'Waiting for success response from ${DOMAIN_NAME}'; sleep 10; done;"
        ExecStartPost=/bin/touch /etc/teamcity/waiter

        [Install]
        WantedBy=multi-user.target