diff --git a/deploy-board/deploy_board/static/css/deploy-board.css b/deploy-board/deploy_board/static/css/deploy-board.css
index 5e626625f9..4d65d4af95 100644
--- a/deploy-board/deploy_board/static/css/deploy-board.css
+++ b/deploy-board/deploy_board/static/css/deploy-board.css
@@ -59,6 +59,43 @@ body {
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
+.btn-critical {
+ background-color: #bf4046;
+ color: white;
+}
+
+.btn-critical:hover {
+ background-color: #d2464d;
+ color: white;
+}
+
+.btn-outline-danger {
+ border: 1px solid #de606d;
+ color: #de606d
+}
+
+.btn-info {
+ background-color: #17a2b8;
+ color: white;
+}
+
+.btn-outline-info {
+ border: 2px dashed #17a2b8;
+ color: #17a2b8;
+ animation: blink-border 1s infinite;
+}
+
+.btn-outline-warning {
+ border: 2px dashed #ffc107;
+ animation: blink-border 1s infinite;
+}
+
+@keyframes blink-border {
+ 50% {
+ border-color: #fff;
+ }
+}
+
.row-centered {
text-align:center;
}
diff --git a/deploy-board/deploy_board/templates/deploys/deploy_progress.html b/deploy-board/deploy_board/templates/deploys/deploy_progress.html
index fbff32f367..00e0728550 100644
--- a/deploy-board/deploy_board/templates/deploys/deploy_progress.html
+++ b/deploy-board/deploy_board/templates/deploys/deploy_progress.html
@@ -192,17 +192,24 @@
{% endif %}
{% elif report.account == "all" %}
-
- {% if report.showMode != "compact" %}{{ agentStat.agent.hostName }}{% endif %}
- {% if report.showMode == "containerStatus" %}
- {% include "deploys/_container_status.html" with healthStatus=agentStat.agent.containerHealthStatus %}
- {% else %}
-
- {% endif %}
-
+ {% if report.showMode == "containerStatus" %}
+
+ {{ agentStat.agent.hostName }}
+
+
+ {% else %}
+
+ {% if report.showMode != "compact" %}{{ agentStat.agent.hostName }}{% endif %}
+
+
+
+ {% endif %}
{% endif %}
{% endfor %}
diff --git a/deploy-board/deploy_board/webapp/templatetags/utils.py b/deploy-board/deploy_board/webapp/templatetags/utils.py
index b81a3235c4..63b64e9e98 100644
--- a/deploy-board/deploy_board/webapp/templatetags/utils.py
+++ b/deploy-board/deploy_board/webapp/templatetags/utils.py
@@ -31,6 +31,7 @@
from deploy_board.webapp.helpers.tags_helper import TagValue
from deploy_board.settings import AWS_PRIMARY_ACCOUNT, AWS_SUB_ACCOUNT
import ast
+from deploy_board.webapp.agent_report import AgentStatistics
register = template.Library()
logger = logging.getLogger(__name__)
@@ -544,7 +545,6 @@ def branchAndCommit(build):
def percentize(deploy):
return "%d%%" % round(deploy.succeeded * 100 / deploy.reported)
-
@register.filter("agentTip")
def agentTip(agentStats):
agent = agentStats.agent
@@ -611,6 +611,72 @@ def agentButton(agentStats):
return 'btn-warning'
+def _is_agent_failed(agent) -> bool:
+ return agent['status'] != "SUCCEEDED" and agent['status'] != "UNKNOWN" or agent['state'] == "PAUSED_BY_SYSTEM"
+
+@register.filter("hostButtonHtmlClass")
+def hostButtonHtmlClass(agentStat: AgentStatistics) -> str:
+ state = agentStat.agent['state']
+ if state == "UNREACHABLE":
+ return "btn btn-default btn-xs host-stale btn-critical"
+ elif _is_agent_failed(agentStat.agent):
+ return "btn btn-default btn-xs btn-outline-danger"
+ elif state == "DELETE" or state == "RESET":
+ return "btn btn-default btn-xs btn-info"
+ elif state == "STOP":
+ return "btn btn-default btn-xs btn-outline-info"
+ elif state == "PAUSED_BY_USER":
+ return "btn btn-default btn-xs btn-outline-warning"
+ return "btn btn-default btn-xs"
+
+@register.filter("hostHealthcheckIcon")
+def hostHealthcheckIcon(agentStat: AgentStatistics) -> str:
+ state = agentStat.agent['state']
+ if state == "DELETE":
+ return "fa fa-trash"
+ elif state == "RESET":
+ return "fa fa-repeat fa-spin"
+ elif state == "UNREACHABLE":
+ return "fa fa-question"
+ elif state == "STOP":
+ return "fa fa-stop"
+ healthcheckResponse: str = agentStat.agent.get("containerHealthStatus", "")
+ if "unhealthy" in healthcheckResponse:
+ return "fa fa-circle color-red"
+ elif "healthy" in healthcheckResponse:
+ return "fa fa-circle color-green"
+ return ""
+
+@register.filter("hostTooltipTitle")
+def hostTooltipTitle(agentStat: AgentStatistics) -> str:
+ state = agentStat.agent['state']
+ if state == "PAUSED_BY_USER":
+ return "Agent is explicitly paused for any deploys"
+ elif state == "PAUSED_BY_SYSTEM":
+ return "Agent failed to deploy and is paused by the system"
+ elif state == "DELETE":
+ return "Agent is removed from the current environment"
+ elif state == "UNREACHABLE":
+ return "Agent is unreachable after not pinging Teletraan control plane within the threshold"
+ elif state == "STOP":
+ return "Agent is gracefully shutting down the service"
+ elif state == "RESET":
+ return "Agent is restarting the deployment"
+ elif not agentStat.isCurrent:
+ if state == "SERVING_BUILD":
+ return "Agent is serving older build and waiting for deploy"
+ elif _is_agent_failed(agentStat.agent):
+ return "Agent is serving older build with failures. Click for details"
+ else:
+ return "Agent is serving older build with failures. Click for details"
+ else:
+ if agentStat.agent['deployStage'] == "SERVING_BUILD":
+ return "Agent is serving the current build successfully"
+ elif _is_agent_failed(agentStat.agent):
+ return "Agent is deploying current build with failures. Click for details"
+ else:
+ return "Agent is deploying current build"
+
@register.filter("agentIcon")
def agentIcon(agentStats):
agent = agentStats.agent