From 08abe4316acc7c9bab1589ddd21167efa769c839 Mon Sep 17 00:00:00 2001 From: Samuel Padgett Date: Tue, 26 Feb 2019 11:31:18 -0500 Subject: [PATCH] Only store swagger.json definitions in sessionStorage sessionStorage has limited space. Only store what we're using for the YAML editor. --- .../__tests__/module/k8s/autocomplete.spec.ts | 22 +++++++++---------- frontend/public/components/edit-yaml.jsx | 15 ++++++++++--- frontend/public/const.js | 1 + frontend/public/module/k8s/autocomplete.ts | 21 +++++++++++------- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/frontend/__tests__/module/k8s/autocomplete.spec.ts b/frontend/__tests__/module/k8s/autocomplete.spec.ts index cf4196de737..fc0b53c046e 100644 --- a/frontend/__tests__/module/k8s/autocomplete.spec.ts +++ b/frontend/__tests__/module/k8s/autocomplete.spec.ts @@ -85,22 +85,20 @@ describe('getCompletions', () => { }); it('invokes callback with appropriate completions for properties', (done) => { - const swagger = { - definitions: { - 'io.k8s.api.apps.v1.Deployment': {}, - 'io.k8s.api.apps.v1.DeploymentSpec': { - properties: { - minReadySeconds: { - description: 'Dummy property', - type: 'integer', - format: 'int32', - }, + const definitions = { + 'io.k8s.api.apps.v1.Deployment': {}, + 'io.k8s.api.apps.v1.DeploymentSpec': { + properties: { + minReadySeconds: { + description: 'Dummy property', + type: 'integer', + format: 'int32', }, }, }, }; sessionMock.getLines = jasmine.createSpy('getLinesSpy').and.returnValue(['kind: Deployment', 'apiVersion: apps/v1']); - spyOn(window.localStorage, 'getItem').and.returnValue(JSON.stringify(swagger)); + spyOn(window.sessionStorage, 'getItem').and.returnValue(JSON.stringify(definitions)); getCompletions(editorMock, sessionMock, position, '', (error, results) => { expect(results.length).toEqual(1); @@ -116,7 +114,7 @@ describe('getCompletions', () => { it('does not provide completion for properties if k8s API spec cannot be retrieved', (done) => { sessionMock.getLines = jasmine.createSpy('getLinesSpy').and.returnValue(['kind: Deployment', 'apiVersion: apps/v1']); - spyOn(window.localStorage, 'getItem').and.returnValue(null); + spyOn(window.sessionStorage, 'getItem').and.returnValue(null); getCompletions(editorMock, sessionMock, position, '', (error, results) => { fail('Should not have been called'); diff --git a/frontend/public/components/edit-yaml.jsx b/frontend/public/components/edit-yaml.jsx index b9e0fe3b1e9..1197223d57c 100644 --- a/frontend/public/components/edit-yaml.jsx +++ b/frontend/public/components/edit-yaml.jsx @@ -18,6 +18,7 @@ import { SafetyFirst } from './safety-first'; import { coFetchJSON } from '../co-fetch'; import { ResourceSidebar } from './sidebars/resource-sidebar'; import { yamlTemplates } from '../models/yaml-templates'; +import { SWAGGER_SESSION_STORAGE_KEY } from '../const'; const { snippetManager } = ace.acequire('ace/snippets'); snippetManager.register([...snippets.values()], 'yaml'); @@ -72,9 +73,17 @@ export const EditYAML = connect(stateToProps)( } // Retrieve k8s API spec for autocompletion - if (!window.sessionStorage.getItem(`${window.SERVER_FLAGS.consoleVersion}--swagger.json`)) { - coFetchJSON('api/kubernetes/swagger.json') - .then(swagger => window.sessionStorage.setItem(`${window.SERVER_FLAGS.consoleVersion}--swagger.json`, JSON.stringify(swagger))); + if (!window.sessionStorage.getItem(SWAGGER_SESSION_STORAGE_KEY)) { + coFetchJSON('api/kubernetes/swagger.json').then(swagger => { + // Only store definitions to reduce the document size. + const json = JSON.stringify(swagger.definitions || {}); + try { + window.sessionStorage.setItem(SWAGGER_SESSION_STORAGE_KEY, json); + } catch (e) { + // eslint-disable-next-line no-console + console.error('Could not store swagger.json', e); + } + }); } } diff --git a/frontend/public/const.js b/frontend/public/const.js index c5fc9fa0ba5..2967e16cd5b 100644 --- a/frontend/public/const.js +++ b/frontend/public/const.js @@ -26,6 +26,7 @@ export const NAMESPACE_LOCAL_STORAGE_KEY = 'dropdown-storage-namespaces'; export const LAST_NAMESPACE_NAME_LOCAL_STORAGE_KEY = `${STORAGE_PREFIX}/last-namespace-name`; export const API_DISCOVERY_RESOURCES_LOCAL_STORAGE_KEY = `${STORAGE_PREFIX}/api-discovery-resources`; export const COMMUNITY_PROVIDERS_WARNING_LOCAL_STORAGE_KEY = `${STORAGE_PREFIX}/community-providers-warning`; +export const SWAGGER_SESSION_STORAGE_KEY = `${STORAGE_PREFIX}/${window.SERVER_FLAGS.consoleVersion}/swagger-definitions`; // Bootstrap user for OpenShift 4.0 clusters export const KUBE_ADMIN_USERNAME = 'kube:admin'; diff --git a/frontend/public/module/k8s/autocomplete.ts b/frontend/public/module/k8s/autocomplete.ts index f97710f46e9..93a346020a7 100644 --- a/frontend/public/module/k8s/autocomplete.ts +++ b/frontend/public/module/k8s/autocomplete.ts @@ -8,6 +8,7 @@ import { ServiceAccountModel, SecretModel, ServiceModel, ConfigMapModel, Alertma import { K8sKind, K8sResourceKind } from '../../module/k8s'; import { k8sListPartialMetadata } from '../../module/k8s/resource'; import { getActiveNamespace } from '../../ui/ui-actions'; +import { SWAGGER_SESSION_STORAGE_KEY } from '../../const'; export type AceSnippet = { content: string; @@ -139,11 +140,11 @@ export const getPropertyCompletions = async(state: Editor, session: IEditSession const kind = valueFor('kind'); const apiVersion = valueFor('apiVersion'); - const swagger: SwaggerAPISpec = JSON.parse(window.sessionStorage.getItem(`${(window as any).SERVER_FLAGS.consoleVersion}--swagger.json`)); + const swaggerDefinitions: SwaggerDefinitions = JSON.parse(window.sessionStorage.getItem(SWAGGER_SESSION_STORAGE_KEY)); - if (kind.length && apiVersion.length && swagger) { - const defKey = Object.keys(swagger.definitions).find(key => key.endsWith(`${apiVersion.replace('/', '.')}.${kind}`)); - const results = Object.keys(_.get(swagger.definitions, [`${defKey}Spec`, 'properties'], {})).map(prop => ({ + if (kind.length && apiVersion.length && swaggerDefinitions) { + const defKey = Object.keys(swaggerDefinitions).find(key => key.endsWith(`${apiVersion.replace('/', '.')}.${kind}`)); + const results = Object.keys(_.get(swaggerDefinitions, [`${defKey}Spec`, 'properties'], {})).map(prop => ({ name: prop, score: 10000, value: prop, @@ -205,14 +206,18 @@ export const getCompletions: Completer['getCompletions'] = (editor, session, pos } }; +export type SwaggerDefinitions = { + [name: string]: { + description: string; + properties: {[prop: string]: {description: string, type: string}}; + } +}; + export type SwaggerAPISpec = { swagger: string; info: {title: string, version: string}; paths: {[path: string]: any}; - definitions: {[name: string]: { - description: string; - properties: {[prop: string]: {description: string, type: string}}; - }}; + definitions: SwaggerDefinitions; }; // TODO: Remove once https://github.com/DefinitelyTyped/DefinitelyTyped/pull/25337 is merged