saddles.html 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <pstm-uri>/saddles</pstm-uri>
  5. <pstm-template>main</pstm-template>
  6. </head>
  7. <body>
  8. <section>
  9. <h2>Saddles</h2>
  10. <p stm-if="saddles == null">Loading…</p>
  11. <div stm-if="saddles != null">
  12. <details>
  13. <summary><strong>Register saddle</strong></summary>
  14. <form stm-action="saddles.register">
  15. <div class="form-row"><label>Name</label>
  16. <input type="text" name="name" required placeholder="saddle-1"></div>
  17. <div class="form-row"><label>Host</label>
  18. <input type="text" name="host" required placeholder="localhost:7100"></div>
  19. <button type="submit">Register</button>
  20. </form>
  21. </details>
  22. <div class="cards">
  23. <section class="card" stm-for-saddle-in="saddles.saddles">
  24. <h3 stm-text="saddle.name">name</h3>
  25. <p><span stm-attribute.class="'badge badge-' + saddle.status" stm-text="saddle.status">status</span>
  26. <span class="muted" stm-text="saddle.host">host</span></p>
  27. <p stm-if="saddle.current_goal_id > 0">Supervising goal:
  28. <a stm-attribute.href="'/goals/' + saddle.current_goal_id"
  29. stm-text="saddle.current_goal_title">goal</a>
  30. <span class="badge badge-kind-goal">goal</span>
  31. <span class="muted" stm-if="saddle.allocated_display.length > 0" stm-text="'since ' + saddle.allocated_display">since</span></p>
  32. <p stm-if="saddle.current_task_id > 0 && saddle.current_goal_id == 0">Current task:
  33. <a stm-attribute.href="'/tasks/' + saddle.current_task_id" stm-text="saddle.current_task_title">task</a>
  34. <span class="muted" stm-if="saddle.allocated_display.length > 0" stm-text="'since ' + saddle.allocated_display">since</span></p>
  35. <p stm-if="saddle.current_task_id == 0" class="muted">No current task</p>
  36. <p><span stm-attribute.class="'badge badge-health-' + saddle.health"
  37. stm-text="saddle.health">healthy</span>
  38. <span class="muted" stm-if="saddle.daemon_state.length > 0"
  39. stm-text="'daemon ' + saddle.daemon_state + (saddle.uptime_display.length > 0 ? ' · up ' + saddle.uptime_display : '')">daemon</span>
  40. <span class="muted" stm-text="'contacted ' + saddle.last_contact_display + ' ago'">contacted</span></p>
  41. <p stm-if="saddle.token.length > 0" class="muted">API token:
  42. <code stm-text="saddle.token">token</code></p>
  43. <details stm-if="saddle.ssh_public_key.length > 0">
  44. <summary>SSH public key</summary>
  45. <p class="muted">Add this as a <strong>deploy key</strong> on the git server
  46. (with write access) so this saddle can clone and push.</p>
  47. <pre class="ssh-key"><code stm-text="saddle.ssh_public_key">key</code></pre>
  48. <button type="button"
  49. stm-attribute.data-clipboard="saddle.ssh_public_key"
  50. onclick="navigator.clipboard.writeText(this.getAttribute('data-clipboard')).then(function () { this.textContent = 'Copied'; }.bind(this))">Copy key</button>
  51. </details>
  52. <p stm-if="saddle.ssh_public_key.length == 0" class="muted">No SSH key reported yet —
  53. it appears here once the daemon generates one.</p>
  54. <details>
  55. <summary>Git identity</summary>
  56. <form stm-action="saddle.update_identity" class="inline">
  57. <label>Committed as</label>
  58. <input type="text" name="git_name" stm-attribute.value="saddle.git_name"
  59. placeholder="saddle-1">
  60. <input type="text" name="git_email" stm-attribute.value="saddle.git_email"
  61. placeholder="saddle-1@example.net">
  62. <button type="submit">Save</button>
  63. <span class="muted">Empty fields fall back to the daemon's default identity.</span>
  64. </form>
  65. </details>
  66. <p stm-if="saddle.capabilities.length > 0">Capabilities:
  67. <span stm-for-capability-in="saddle.capabilities" stm-key="capability.link_id">
  68. <span class="badge"><span stm-text="capability.name">tag</span>
  69. <button type="button" class="inline chip-remove"
  70. stm-action="capability.detach" stm-confirm="Remove this capability?">×</button></span>
  71. </span>
  72. </p>
  73. <p stm-if="saddle.capabilities.length == 0" class="muted">No capabilities — matches only tasks with none required.</p>
  74. <form class="inline" stm-if="saddles.capability_options.length > 0"
  75. stm-action="saddle.attach_capability">
  76. <label stm-attribute.for="'cap-' + saddle.id">Add capability</label>
  77. <select stm-attribute.id="'cap-' + saddle.id" name="capability_id" required>
  78. <option stm-for-option-in="saddles.capability_options" stm-attribute.value="option.id"
  79. stm-text="option.name">capability</option>
  80. </select>
  81. <button type="submit">Add</button>
  82. </form>
  83. <form class="inline">
  84. <button type="button" stm-action="saddle.refresh">Refresh status</button>
  85. <button type="button" stm-action="saddle.unregister" stm-confirm="Remove this saddle? A running task is re-queued.">Remove</button>
  86. </form>
  87. </section>
  88. <section class="card" stm-if="saddles.saddles.length == 0">
  89. <p class="muted">No saddles registered. The dispatcher pairs queued tasks with idle saddles automatically.</p>
  90. </section>
  91. </div>
  92. <h3>Capabilities</h3>
  93. <p class="muted">Tags the dispatcher routes by: a task is only assigned to a saddle carrying every
  94. tag the task requires. Manage a saddle's tags on its card above; require tags on a task's page.</p>
  95. <details>
  96. <summary><strong>New capability</strong></summary>
  97. <form stm-action="saddles.create_capability" class="inline">
  98. <label for="new-capability">Name</label>
  99. <input type="text" id="new-capability" name="name" required placeholder="gpu">
  100. <button type="submit">Create capability</button>
  101. </form>
  102. </details>
  103. <table>
  104. <thead><tr><th>Tag</th><th>Saddles carrying it</th><th>Tasks requiring it</th><th></th></tr></thead>
  105. <tbody>
  106. <tr stm-for-capability-in="saddles.capabilities">
  107. <td><span class="badge" stm-text="capability.name">tag</span></td>
  108. <td stm-text="capability.saddle_count">0</td>
  109. <td stm-text="capability.task_count">0</td>
  110. <td><button type="button" stm-action="capability.delete"
  111. stm-confirm="Delete this capability everywhere?">Delete</button></td>
  112. </tr>
  113. <tr stm-if="saddles.capabilities.length == 0">
  114. <td colspan="4" class="muted">No capabilities defined yet.</td>
  115. </tr>
  116. </tbody>
  117. </table>
  118. </div>
  119. </section>
  120. </body>
  121. </html>