diff --git a/inventory_provider/static/update.css b/inventory_provider/static/update.css
new file mode 100644
index 0000000000000000000000000000000000000000..18c8c373b516ea411cb0b3e33bda7d6c31df5ad7
--- /dev/null
+++ b/inventory_provider/static/update.css
@@ -0,0 +1,12 @@
+.grid-container {
+  display: grid;
+}
+
+.ok {
+
+}
+
+.error {
+  color: red;
+  font-weight: bold;
+}
diff --git a/inventory_provider/static/update.html b/inventory_provider/static/update.html
new file mode 100644
index 0000000000000000000000000000000000000000..cb2ce23af994576ac8e4fff946eb006a958f393d
--- /dev/null
+++ b/inventory_provider/static/update.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<html ng-app="inventoryApp">
+  <head>
+    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.5/angular.min.js"></script>
+    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
+    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
+    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
+    <script src="update.js"></script>
+    <link rel="stylesheet" href="update.css">
+  </head>
+  <body>
+
+    <div ng-controller="update">
+      <div class="grid-container">
+
+        <div class="grid-item">
+          <button type="button"
+                  class="btn btn-primary btn-lg"
+                  ng-click="launch_update()"
+                  ng-disabled="latch_pending">Update Inventory Provider</button>
+        </div>
+
+        <div class="grid-item" ng-class="latch_error||update_request_error ? 'error' : 'ok'">
+          {{ latch_info }}
+        </div>
+
+        <div class="grid-item" ng-class="update_request_error ? 'error' : 'ok'">
+          {{ update_request_status }}
+        </div>
+
+      </div>
+    </div>
+  </body>
+</html>
\ No newline at end of file
diff --git a/inventory_provider/static/update.js b/inventory_provider/static/update.js
new file mode 100644
index 0000000000000000000000000000000000000000..d2b729b9158968ee894fb462390680afaa828e71
--- /dev/null
+++ b/inventory_provider/static/update.js
@@ -0,0 +1,64 @@
+var myApp = angular.module('inventoryApp', []);
+
+myApp.controller('update', function($scope, $http, $timeout) {
+
+    $scope.latch_pending = false;
+    $scope.latch_error = false;
+    $scope.latch_info = "module version ????";
+
+    $scope.update_request_status = "";
+    $scope.update_request_error = false;
+
+    $scope.check_status = function() {
+
+        $http({
+            method: 'GET',
+            url: window.location.origin + "/version"
+        }).then(
+            /* ok response */
+            function(rsp) {
+                console.log('got version rsp: ' + JSON.stringify(rsp.data));
+                $scope.latch_info = "module version " + rsp.data.module;
+                $scope.latch_pending = rsp.data.latch.pending;
+                $scope.latch_error = rsp.data.latch.failure;
+                if (!$scope.latch_pending) {
+                    $scope.update_request_status = "";
+                }
+                $timeout($scope.check_status, 5000);
+            },
+            /* error response */
+            function(rsp) {
+                console.log("got error response: " + JSON.stringify(rsp));
+                $scope.latch_info = "communication error";
+                $scope.latch_pending = false;
+                $scope.latch_error = true;
+                $timeout($scope.check_status(), 5000);
+            }
+        );
+    }
+
+    $scope.launch_update = function() {
+        $scope.update_request_status = "sending update request";
+        $scope.update_request_error = false;
+        $scope.latch_pending = true;
+        $http({
+            method: 'GET',
+            url: window.location.origin + "/jobs/update"
+        }).then(
+            /* ok response */
+            function(rsp) {
+                $scope.update_request_status = "update is running";
+                $scope.update_request_error = false;
+                console.log('got update rsp: ' + JSON.stringify(rsp.data));
+            },
+            /* error response */
+            function(rsp) {
+                $scope.update_request_status = "update request failed";
+                $scope.update_request_error = true;
+                console.log("got error response: " + JSON.stringify(rsp));
+            }
+        );
+    }
+
+    $scope.check_status();
+});
\ No newline at end of file