From efe6cced900efa3a92cd92fc4e56aeba99b3df00 Mon Sep 17 00:00:00 2001 From: alesstimec Date: Tue, 11 Jul 2023 15:31:59 +0200 Subject: [PATCH] Removes the dashboard resource. JIMM will no longer be serving the dashboard files since we have a juju dashboard charm. --- charms/jimm-k8s/metadata.yaml | 4 - charms/jimm-k8s/src/charm.py | 95 +---------------- charms/jimm-k8s/tests/unit/test_charm.py | 58 ---------- charms/jimm/metadata.yaml | 4 - charms/jimm/src/charm.py | 40 ------- charms/jimm/tests/test_charm.py | 28 +---- internal/dashboard/dashboard.go | 130 +---------------------- internal/dashboard/dashboard_test.go | 103 ------------------ 8 files changed, 5 insertions(+), 457 deletions(-) diff --git a/charms/jimm-k8s/metadata.yaml b/charms/jimm-k8s/metadata.yaml index 76431f392..4f7a871a6 100644 --- a/charms/jimm-k8s/metadata.yaml +++ b/charms/jimm-k8s/metadata.yaml @@ -61,10 +61,6 @@ containers: resource: jimm-image resources: - dashboard: - type: file - filename: dashboard.tar.xz - description: "juju dashboard tarball." jimm-image: type: oci-image description: OCI image for JIMM. diff --git a/charms/jimm-k8s/src/charm.py b/charms/jimm-k8s/src/charm.py index ad821323f..5563607e7 100755 --- a/charms/jimm-k8s/src/charm.py +++ b/charms/jimm-k8s/src/charm.py @@ -18,7 +18,6 @@ import hashlib import json import logging -import os import socket import hvac @@ -43,16 +42,9 @@ IngressPerAppRequirer, IngressPerAppRevokedEvent, ) -from ops import pebble from ops.charm import CharmBase, RelationJoinedEvent from ops.main import main -from ops.model import ( - ActiveStatus, - BlockedStatus, - MaintenanceStatus, - ModelError, - WaitingStatus, -) +from ops.model import ActiveStatus, BlockedStatus, WaitingStatus from state import State, requires_state, requires_state_setter @@ -167,8 +159,6 @@ def __init__(self, *args): self._agent_filename = "/root/config/agent.json" self._vault_secret_filename = "/root/config/vault_secret.json" self._vault_path = "charm-jimm-k8s-creds" - self._dashboard_path = "/root/dashboard" - self._dashboard_hash_path = "/root/dashboard/hash" def _on_peer_relation_changed(self, event): self._update_workload(event) @@ -217,7 +207,6 @@ def _update_workload(self, event): self._ensure_bakery_agent_file(event) self._ensure_vault_file(event) - self._install_dashboard(event) dns_name = self._get_dns_name(event) if not dns_name: @@ -249,9 +238,6 @@ def _update_workload(self, event): if self.model.unit.is_leader(): config_values["JIMM_WATCH_CONTROLLERS"] = "1" - if container.exists(self._dashboard_path): - config_values["JIMM_DASHBOARD_LOCATION"] = self._dashboard_path - # remove empty configuration values config_values = {key: value for key, value in config_values.items() if value} @@ -382,85 +368,6 @@ def _ready(self): self.unit.status = WaitingStatus("waiting for jimm workload") return False - def _install_dashboard(self, event): - container = self.unit.get_container(WORKLOAD_CONTAINER) - - # if we can't connect to the container we should defer - # this event. - if not container.can_connect(): - event.defer() - return - - # fetch the resource filename - try: - dashboard_file = self.model.resources.fetch("dashboard") - except ModelError: - dashboard_file = None - - # if the resource is not specified, we can return - # as there is nothing to install. - if not dashboard_file: - return - - # if the resource file is empty, we can return - # as there is nothing to install. - if os.path.getsize(dashboard_file) == 0: - return - - dashboard_changed = False - - # compute the hash of the dashboard tarball. - dashboard_hash = self._hash(dashboard_file) - - # check if we the file containing the dashboard - # hash exists. - if container.exists(self._dashboard_hash_path): - # if it does, compare the stored hash with the - # hash of the dashboard tarball. - hash = container.pull(self._dashboard_hash_path) - existing_hash = str(hash.read()) - # if the two hashes do not match - # the resource must have changed. - if not dashboard_hash == existing_hash: - dashboard_changed = True - else: - dashboard_changed = True - - # if the resource file has not changed, we can - # return as there is no need to push the same - # dashboard content to the container. - if not dashboard_changed: - return - - self.unit.status = MaintenanceStatus("installing dashboard") - - # remove the existing dashboard from the workload/ - if container.exists(self._dashboard_path): - container.remove_path(self._dashboard_path, recursive=True) - - container.make_dir(self._dashboard_path, make_parents=True) - - with open(dashboard_file, "rb") as f: - container.push(os.path.join(self._dashboard_path, "dashboard.tar.bz2"), f) - - process = container.exec( - [ - "tar", - "xvf", - os.path.join(self._dashboard_path, "dashboard.tar.bz2"), - "-C", - self._dashboard_path, - ] - ) - try: - process.wait_output() - except pebble.ExecError as e: - logger.error("error running untaring the dashboard. error code {}".format(e.exit_code)) - for line in e.stderr.splitlines(): - logger.error(" %s", line) - - self._push_to_workload(self._dashboard_hash_path, dashboard_hash, event) - def _get_network_address(self, event): return str(self.model.get_binding(event.relation).network.egress_subnets[0].network_address) diff --git a/charms/jimm-k8s/tests/unit/test_charm.py b/charms/jimm-k8s/tests/unit/test_charm.py index 9c72b3be4..e67795c56 100644 --- a/charms/jimm-k8s/tests/unit/test_charm.py +++ b/charms/jimm-k8s/tests/unit/test_charm.py @@ -4,10 +4,8 @@ # Learn more about testing at: https://juju.is/docs/sdk/testing -import io import json import pathlib -import tarfile import tempfile import unittest from unittest.mock import patch @@ -172,62 +170,6 @@ def test_bakery_configuration(self): }, ) - @patch("ops.model.Container.exec") - def test_install_dashboard(self, exec): - exec.unwrap.return_value = MockExec() - - container = self.harness.model.unit.get_container("jimm") - - self.harness.add_resource("dashboard", self.dashboard_tarfile()) - - self.harness.update_config(MINIMAL_CONFIG) - self.harness.charm.on.jimm_pebble_ready.emit(container) - - plan = self.harness.get_container_pebble_plan("jimm") - self.assertEqual( - plan.to_dict(), - { - "services": { - "jimm": { - "summary": "JAAS Intelligent Model Manager", - "startup": "disabled", - "override": "merge", - "command": "/root/jimmsrv", - "environment": { - "CANDID_URL": "test-candid-url", - "JIMM_LISTEN_ADDR": ":8080", - "JIMM_DASHBOARD_LOCATION": "/root/dashboard", - "JIMM_DNS_NAME": "juju-jimm-k8s-0.juju-jimm-k8s-endpoints.None.svc.cluster.local", - "JIMM_LOG_LEVEL": "info", - "JIMM_UUID": "1234567890", - "JIMM_WATCH_CONTROLLERS": "1", - }, - } - } - }, - ) - - self.assertEqual(container.exists("/root/dashboard"), True) - self.assertEqual(container.isdir("/root/dashboard"), True) - self.assertEqual(container.exists("/root/dashboard/dashboard.tar.bz2"), True) - self.assertEqual(container.exists("/root/dashboard/hash"), True) - - def dashboard_tarfile(self): - dashboard_archive = io.BytesIO() - - data = bytes("Hello world", "utf-8") - f = io.BytesIO(initial_bytes=data) - with tarfile.open(fileobj=dashboard_archive, mode="w:bz2") as tar: - info = tarfile.TarInfo("README.md") - info.size = len(data) - tar.addfile(info, f) - tar.close() - - dashboard_archive.flush() - dashboard_archive.seek(0) - data = dashboard_archive.read() - return data - def test_dashboard_relation_joined(self): harness = Harness(JimmOperatorCharm) self.addCleanup(harness.cleanup) diff --git a/charms/jimm/metadata.yaml b/charms/jimm/metadata.yaml index 5bb021cd6..e0bf9fa51 100644 --- a/charms/jimm/metadata.yaml +++ b/charms/jimm/metadata.yaml @@ -47,7 +47,3 @@ resources: type: file filename: jimm.snap description: Snap containing the JIMM server. - dashboard: - type: file - filename: dashboard.tar.bz2 - description: "Tarball containing the Juju Dashboard." diff --git a/charms/jimm/src/charm.py b/charms/jimm/src/charm.py index 6f543d58f..f352411e9 100755 --- a/charms/jimm/src/charm.py +++ b/charms/jimm/src/charm.py @@ -10,7 +10,6 @@ import shutil import socket import subprocess -import tarfile import urllib import hvac @@ -60,7 +59,6 @@ def __init__(self, *args): self._agent_filename = "/var/snap/jimm/common/agent.json" self._vault_secret_filename = "/var/snap/jimm/common/vault_secret.json" self._workload_filename = "/snap/bin/jimm" - self._dashboard_path = "/var/snap/jimm/common/dashboard" self._rsyslog_conf_path = "/etc/rsyslog.d/10-jimm.conf" self._logrotate_conf_path = "/etc/logrotate.d/jimm" @@ -93,7 +91,6 @@ def _on_install(self, _): """Install the JIMM software.""" self._write_service_file() self._install_snap() - self._install_dashboard() self._setup_logging() self._on_update_status(None) @@ -108,7 +105,6 @@ def _on_upgrade_charm(self, _): """Upgrade the charm software.""" self._write_service_file() self._install_snap() - self._install_dashboard() self._setup_logging() if self._ready(): self.restart() @@ -127,8 +123,6 @@ def _on_config_changed(self, _): "uuid": self.config.get("uuid"), "dashboard_location": self.config.get("juju-dashboard-location"), } - if os.path.exists(self._dashboard_path): - args["dashboard_location"] = self._dashboard_path with open(self._env_filename(), "wt") as f: f.write(self._render_template("jimm.env", **args)) @@ -283,34 +277,6 @@ def _install_snap(self): return self._snap("install", "--dangerous", path) - def _install_dashboard(self): - try: - path = self.model.resources.fetch("dashboard") - except ModelError: - path = None - - if not path: - return - - if self._dashboard_resource_nonempty(): - new_dashboard_path = self._dashboard_path + ".new" - old_dashboard_path = self._dashboard_path + ".old" - shutil.rmtree(new_dashboard_path, ignore_errors=True) - shutil.rmtree(old_dashboard_path, ignore_errors=True) - os.mkdir(new_dashboard_path) - - self.unit.status = MaintenanceStatus("installing dashboard") - with tarfile.open(path, mode="r:bz2") as tf: - tf.extractall(new_dashboard_path) - - # Change the owner/group of all extracted files to root/wheel. - for name in tf.getnames(): - os.chown(os.path.join(new_dashboard_path, name), 0, 0) - - if os.path.exists(self._dashboard_path): - os.rename(self._dashboard_path, old_dashboard_path) - os.rename(new_dashboard_path, self._dashboard_path) - def _setup_logging(self): """Install the logging configuration.""" shutil.copy( @@ -323,12 +289,6 @@ def _setup_logging(self): ) self._systemctl("restart", "rsyslog") - def _dashboard_resource_nonempty(self): - dashboard_file = self.model.resources.fetch("dashboard") - if dashboard_file: - return os.path.getsize(dashboard_file) != 0 - return False - def _bakery_agent_file(self): url = self.config.get("candid-url", "") username = self.config.get("candid-agent-username", "") diff --git a/charms/jimm/tests/test_charm.py b/charms/jimm/tests/test_charm.py index 47ab07351..2732f64e8 100644 --- a/charms/jimm/tests/test_charm.py +++ b/charms/jimm/tests/test_charm.py @@ -3,14 +3,12 @@ # # Learn more about testing at: https://juju.is/docs/sdk/testing -import io import ipaddress import json import os import pathlib import shutil import socket -import tarfile import tempfile import unittest from http.server import BaseHTTPRequestHandler, HTTPServer @@ -47,26 +45,9 @@ def setUp(self): ) self.harness.charm.framework.charm_dir = pathlib.Path(self.tempdir.name) - def dashboard_tarfile(self): - dashboard_archive = io.BytesIO() - - data = bytes("Hello world", "utf-8") - f = io.BytesIO(initial_bytes=data) - with tarfile.open(fileobj=dashboard_archive, mode="w:bz2") as tar: - info = tarfile.TarInfo("README.md") - info.size = len(data) - tar.addfile(info, f) - tar.close() - - dashboard_archive.flush() - dashboard_archive.seek(0) - data = dashboard_archive.read() - return data - def test_install(self): service_file = os.path.join(self.harness.charm.charm_dir, "juju-jimm.service") self.harness.add_resource("jimm-snap", "Test data") - self.harness.add_resource("dashboard", self.dashboard_tarfile()) self.harness.charm.on.install.emit() self.assertTrue(os.path.exists(service_file)) self.assertTrue(os.path.exists(self.harness.charm._logrotate_conf_path)) @@ -75,7 +56,6 @@ def test_install(self): self.assertEqual(self.harness.charm._snap.call_args.args[0], "install") self.assertEqual(self.harness.charm._snap.call_args.args[1], "--dangerous") self.assertTrue(str(self.harness.charm._snap.call_args.args[2]).endswith("jimm.snap")) - self.chownmock.assert_has_calls([call(self.tempdir.name + "/dashboard.new/README.md", 0, 0)]) def test_start(self): self.harness.charm.on.start.emit() @@ -98,7 +78,6 @@ def test_start_ready(self): def test_upgrade_charm(self): service_file = os.path.join(self.harness.charm.charm_dir, "juju-jimm.service") self.harness.add_resource("jimm-snap", "Test data") - self.harness.add_resource("dashboard", self.dashboard_tarfile()) self.harness.charm.on.upgrade_charm.emit() self.assertTrue(os.path.exists(service_file)) self.assertTrue(os.path.exists(self.harness.charm._logrotate_conf_path)) @@ -107,7 +86,6 @@ def test_upgrade_charm(self): self.assertEqual(self.harness.charm._snap.call_args.args[0], "install") self.assertEqual(self.harness.charm._snap.call_args.args[1], "--dangerous") self.assertTrue(str(self.harness.charm._snap.call_args.args[2]).endswith("jimm.snap")) - self.chownmock.assert_has_calls([call(self.tempdir.name + "/dashboard.new/README.md", 0, 0)]) def test_upgrade_charm_ready(self): service_file = os.path.join(self.harness.charm.charm_dir, "juju-jimm.service") @@ -130,7 +108,6 @@ def test_upgrade_charm_ready(self): def test_config_changed(self): config_file = os.path.join(self.harness.charm.charm_dir, "juju-jimm.env") - os.mkdir(self.tempdir.name + "/dashboard") self.harness.update_config( { "candid-url": "https://candid.example.com", @@ -150,7 +127,7 @@ def test_config_changed(self): self.assertEqual(lines[2].strip(), "JIMM_ADMINS=user1 user2 group1") self.assertEqual( lines[4].strip(), - "JIMM_DASHBOARD_LOCATION=" + self.tempdir.name + "/dashboard", + "JIMM_DASHBOARD_LOCATION=https://jaas.ai/models", ) self.assertEqual(lines[7].strip(), "JIMM_DNS_NAME=" + "jimm.example.com") self.assertEqual(lines[9].strip(), "JIMM_LOG_LEVEL=debug") @@ -186,7 +163,6 @@ def test_config_changed_redirect_to_dashboard(self): def test_config_changed_ready(self): config_file = os.path.join(self.harness.charm.charm_dir, "juju-jimm.env") - os.mkdir(self.tempdir.name + "/dashboard") with open(self.harness.charm._env_filename("db"), "wt") as f: f.write("test") self.harness.update_config( @@ -206,7 +182,7 @@ def test_config_changed_ready(self): self.assertEqual(lines[2].strip(), "JIMM_ADMINS=user1 user2 group1") self.assertEqual( lines[4].strip(), - "JIMM_DASHBOARD_LOCATION=" + self.tempdir.name + "/dashboard", + "JIMM_DASHBOARD_LOCATION=https://jaas.ai/models", ) self.assertEqual(lines[7].strip(), "JIMM_LOG_LEVEL=info") self.assertEqual(lines[8].strip(), "JIMM_UUID=caaa4ba4-e2b5-40dd-9bf3-2bd26d6e17aa") diff --git a/internal/dashboard/dashboard.go b/internal/dashboard/dashboard.go index 0e2540921..7d0542e9d 100644 --- a/internal/dashboard/dashboard.go +++ b/internal/dashboard/dashboard.go @@ -6,18 +6,10 @@ package dashboard import ( - "bytes" "context" - "encoding/json" "net/http" "net/url" - "os" - "path" - "path/filepath" - "text/template" - "time" - "github.com/juju/version/v2" "github.com/juju/zaputil/zapctx" "go.uber.org/zap" ) @@ -40,126 +32,8 @@ func Handler(ctx context.Context, loc string, publicDNSname string) http.Handler } if u != nil && u.IsAbs() { mux.Handle(dashboardPath, http.RedirectHandler(loc, http.StatusPermanentRedirect)) - return mux + } else { + zapctx.Warn(ctx, "not redirecting to the dashboard", zap.String("dashboard_location", loc)) } - - f, err := os.Open(loc) - if err != nil { - zapctx.Warn(ctx, "error reading dashboard path", zap.Error(err)) - return mux - } - defer f.Close() - des, err := f.ReadDir(0) - if err != nil { - zapctx.Warn(ctx, "error reading dashboard path", zap.Error(err)) - return mux - } - - for _, de := range des { - fn := filepath.Join(loc, de.Name()) - if de.IsDir() { - root := "/" + de.Name() + "/" - mux.Handle(root, http.StripPrefix(root, http.FileServer(http.Dir(fn)))) - continue - } - hnd := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - http.ServeFile(w, req, fn) - }) - switch de.Name() { - case "index.html": - // serve index.html if there is nothing better to serve. - mux.Handle("/", hnd) - mux.Handle(dashboardPath, http.RedirectHandler("/", http.StatusSeeOther)) - case "config.js": - continue - case "config.js.go": - modTime := time.Now() - buf, err := os.ReadFile(fn) - if err != nil { - zapctx.Error(ctx, "error reading config.js.go", zap.Error(err)) - continue - } - t, err := template.New("").Parse(string(buf)) - if err != nil { - zapctx.Error(ctx, "error parsing config.js.go", zap.Error(err)) - continue - } - var w bytes.Buffer - configParams["baseControllerURL"] = publicDNSname - if err := t.Execute(&w, configParams); err != nil { - zapctx.Error(ctx, "error executing config.js.go", zap.Error(err)) - continue - } - content := bytes.NewReader(w.Bytes()) - mux.Handle("/config.js", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - http.ServeContent(w, req, "config.js", modTime, content) - })) - case "version.json": - modTime := time.Now() - buf, err := os.ReadFile(fn) - if err != nil { - zapctx.Error(ctx, "error reading version.json", zap.Error(err)) - continue - } - var fVersion struct { - Version string `json:"version` - GitSHA string `json:"git-sha"` - } - err = json.Unmarshal(buf, &fVersion) - if err != nil { - zapctx.Error(ctx, "failed to unmarshal version.json", zap.Error(err)) - continue - } - ver, err := version.Parse(fVersion.Version) - if err != nil { - zapctx.Error(ctx, - "invalid dashboard version number", - zap.Error(err), - zap.String("version", fVersion.Version), - ) - continue - } - type guiArchiveVersion struct { - // Version holds the Juju GUI version number. - Version version.Number `json:"version"` - // SHA256 holds the SHA256 hash of the GUI tar.bz2 archive. - SHA256 string `json:"sha256"` - // Current holds whether this specific version is the current one served - // by the controller. - Current bool `json:"current"` - } - type guiArchiveResponse struct { - Versions []guiArchiveVersion `json:"versions"` - } - - versions := guiArchiveResponse{ - Versions: []guiArchiveVersion{{ - Version: ver, - SHA256: fVersion.GitSHA, - Current: true, - }}, - } - data, err := json.Marshal(versions) - if err != nil { - zapctx.Error(ctx, "failed to marshal gui archive versions", zap.Error(err)) - continue - } - content := bytes.NewReader(data) - mux.Handle("/gui-archive", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - http.ServeContent(w, req, "gui-archive.json", modTime, content) - })) - default: - mux.Handle(path.Join("/", de.Name()), hnd) - } - } - return mux } - -// configParams holds the parameters that need to be provided to the -// config.js.go template for a JAAS dashboard deployement. -var configParams = map[string]interface{}{ - "baseAppURL": "/", - "identityProviderAvailable": true, - "isJuju": false, -} diff --git a/internal/dashboard/dashboard_test.go b/internal/dashboard/dashboard_test.go index 4df31a9b2..a5e6a599f 100644 --- a/internal/dashboard/dashboard_test.go +++ b/internal/dashboard/dashboard_test.go @@ -4,7 +4,6 @@ package dashboard_test import ( "context" - "io" "net/http" "net/http/httptest" "os" @@ -60,79 +59,6 @@ func TestDashboardRedirect(t *testing.T) { c.Check(resp.Header.Get("Location"), qt.Equals, "https://example.com/dashboard") } -func TestDashboardFromPath(t *testing.T) { - c := qt.New(t) - - dir := c.TempDir() - err := os.WriteFile(filepath.Join(dir, "config.js.go"), []byte(configFile), 0444) - c.Assert(err, qt.Equals, nil) - err = os.WriteFile(filepath.Join(dir, "index.html"), []byte(indexFile), 0444) - c.Assert(err, qt.Equals, nil) - err = os.WriteFile(filepath.Join(dir, "test"), []byte(testFile), 0444) - c.Assert(err, qt.Equals, nil) - - hnd := dashboard.Handler(context.Background(), dir, "http://jimm.canonical.com") - rr := httptest.NewRecorder() - req, err := http.NewRequest("GET", "/dashboard", nil) - c.Assert(err, qt.IsNil) - hnd.ServeHTTP(rr, req) - resp := rr.Result() - c.Check(resp.StatusCode, qt.Equals, http.StatusSeeOther) - c.Check(resp.Header.Get("Location"), qt.Equals, "/") - - rr = httptest.NewRecorder() - req, err = http.NewRequest("GET", "/", nil) - c.Assert(err, qt.IsNil) - hnd.ServeHTTP(rr, req) - resp = rr.Result() - c.Check(resp.StatusCode, qt.Equals, http.StatusOK) - buf, err := io.ReadAll(resp.Body) - c.Assert(err, qt.IsNil) - c.Check(string(buf), qt.Equals, indexFile) - - rr = httptest.NewRecorder() - req, err = http.NewRequest("GET", "/config.js", nil) - c.Assert(err, qt.IsNil) - hnd.ServeHTTP(rr, req) - resp = rr.Result() - c.Check(resp.StatusCode, qt.Equals, http.StatusOK) - buf, err = io.ReadAll(resp.Body) - c.Assert(err, qt.IsNil) - c.Check(string(buf), qt.Equals, `var jujuDashboardConfig = { - // API host to allow app to connect and retrieve models - baseControllerURL: "http://jimm.canonical.com", - // Configurable base url to allow deploying to different paths. - baseAppURL: "/", - // If true then identity will be provided by a third party provider. - identityProviderAvailable: true, - // Is this application being rendered in Juju and not JAAS. This flag should - // only be used for superficial updates like logos. Use feature detection - // for other environment features. - isJuju: false, -}; -`) - - rr = httptest.NewRecorder() - req, err = http.NewRequest("GET", "/test", nil) - c.Assert(err, qt.IsNil) - hnd.ServeHTTP(rr, req) - resp = rr.Result() - c.Check(resp.StatusCode, qt.Equals, http.StatusOK) - buf, err = io.ReadAll(resp.Body) - c.Assert(err, qt.IsNil) - c.Check(string(buf), qt.Equals, testFile) - - rr = httptest.NewRecorder() - req, err = http.NewRequest("GET", "/models/alice@external/test", nil) - c.Assert(err, qt.IsNil) - hnd.ServeHTTP(rr, req) - resp = rr.Result() - c.Check(resp.StatusCode, qt.Equals, http.StatusOK) - buf, err = io.ReadAll(resp.Body) - c.Assert(err, qt.IsNil) - c.Check(string(buf), qt.Equals, indexFile) -} - func TestInvalidLocation(t *testing.T) { c := qt.New(t) @@ -160,32 +86,3 @@ func TestLocationNotDirectory(t *testing.T) { resp := rr.Result() c.Check(resp.StatusCode, qt.Equals, http.StatusNotFound) } - -func TestGUIArchiveEndpoint(t *testing.T) { - c := qt.New(t) - - dir := c.TempDir() - err := os.WriteFile(filepath.Join(dir, "config.js.go"), []byte(configFile), 0444) - c.Assert(err, qt.Equals, nil) - err = os.WriteFile(filepath.Join(dir, "index.html"), []byte(indexFile), 0444) - c.Assert(err, qt.Equals, nil) - err = os.WriteFile(filepath.Join(dir, "test"), []byte(testFile), 0444) - c.Assert(err, qt.Equals, nil) - err = os.WriteFile(filepath.Join(dir, "version.json"), []byte(versionFile), 0444) - c.Assert(err, qt.Equals, nil) - - hnd := dashboard.Handler(context.Background(), dir, "http://jimm.canonical.com") - rr := httptest.NewRecorder() - req, err := http.NewRequest("GET", "/gui-archive", nil) - c.Assert(err, qt.IsNil) - hnd.ServeHTTP(rr, req) - resp := rr.Result() - c.Check(resp.StatusCode, qt.Equals, http.StatusOK) - buf, err := io.ReadAll(resp.Body) - c.Assert(err, qt.IsNil) - c.Check( - string(buf), - qt.Equals, - `{"versions":[{"version":"0.8.1","sha256":"34388e4b0b3e68e2c2ba342cb45f0f21d248fd3c","current":true}]}`, - ) -}