From a9cebe5278cbfa9037dcae0ad4a2cb3071059e1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20G=C3=A1mez?= Date: Wed, 6 Oct 2021 09:32:56 +0200 Subject: [PATCH] Remove all the ServiceCatalog logic (#3515) Signed-off-by: Antonio Gamez Diaz --- dashboard/src/actions/apps.test.tsx | 2 +- dashboard/src/actions/catalog.test.tsx | 583 -------------------- dashboard/src/actions/catalog.ts | 263 --------- dashboard/src/actions/index.ts | 2 - dashboard/src/shared/ClusterServiceClass.ts | 59 -- dashboard/src/shared/ServiceBinding.ts | 119 ---- dashboard/src/shared/ServiceCatalog.ts | 137 ----- dashboard/src/shared/ServiceInstance.ts | 79 --- dashboard/src/shared/url.ts | 8 - 9 files changed, 1 insertion(+), 1251 deletions(-) delete mode 100644 dashboard/src/actions/catalog.test.tsx delete mode 100644 dashboard/src/actions/catalog.ts delete mode 100644 dashboard/src/shared/ClusterServiceClass.ts delete mode 100644 dashboard/src/shared/ServiceBinding.ts delete mode 100644 dashboard/src/shared/ServiceCatalog.ts delete mode 100644 dashboard/src/shared/ServiceInstance.ts diff --git a/dashboard/src/actions/apps.test.tsx b/dashboard/src/actions/apps.test.tsx index 59c85040134..964bc5a71c3 100644 --- a/dashboard/src/actions/apps.test.tsx +++ b/dashboard/src/actions/apps.test.tsx @@ -239,7 +239,7 @@ describe("upgradeApp", () => { "kubeapps", ); - it("calls ServiceBinding.delete and returns true if no error", async () => { + it("calls App.upgrade and returns true if no error", async () => { App.upgrade = jest.fn().mockImplementationOnce(() => true); const res = await store.dispatch(provisionCMD); expect(res).toBe(true); diff --git a/dashboard/src/actions/catalog.test.tsx b/dashboard/src/actions/catalog.test.tsx deleted file mode 100644 index ed991c3ff80..00000000000 --- a/dashboard/src/actions/catalog.test.tsx +++ /dev/null @@ -1,583 +0,0 @@ -import configureMockStore from "redux-mock-store"; -import thunk from "redux-thunk"; -import { ServiceBinding } from "shared/ServiceBinding"; -import { IServiceBroker, IServicePlan, ServiceCatalog } from "shared/ServiceCatalog"; -import { IServiceInstance, ServiceInstance } from "shared/ServiceInstance"; -import { getType } from "typesafe-actions"; -import actions from "."; - -const { catalog: catalogActions } = actions; - -const mockStore = configureMockStore([thunk]); -const broker = { metadata: { name: "wall-street" } } as IServiceBroker; -const servicePlan = { metadata: { name: "bubble-it-up" } } as IServicePlan; -const serviceInstance = { metadata: { name: "25-years-mortgage" } } as IServiceInstance; -const bindingWithSecret = { binding: "binding", secret: "secret" } as any; -const clusterClass = { metadata: { name: "cluster-class" } } as any; - -let store: any; -const testArgs = { - releaseName: "my-release", - kubeappsCluster: "kubeappsCluster", - namespace: "my-namespace", - className: "my-class", - planName: "myPlan", - bindingName: "my-binding", - params: {}, - instanceName: "my-instance", -}; -let boomFn: any; -const errorPayload = (op: string) => ({ err: new Error("Boom!"), op }); - -beforeEach(() => { - store = mockStore({ - config: { - kubeappsCluster: testArgs.kubeappsCluster, - }, - clusters: { - currentCluster: testArgs.kubeappsCluster, - }, - }); - - ServiceInstance.create = jest.fn().mockImplementationOnce(() => { - return { metadata: { name: testArgs.instanceName } }; - }); - ServiceInstance.list = jest.fn().mockImplementationOnce(() => { - return [serviceInstance]; - }); - ServiceBinding.create = jest.fn().mockImplementationOnce(() => { - return { metadata: { name: testArgs.bindingName } }; - }); - ServiceBinding.delete = jest.fn(); - ServiceBinding.list = jest.fn().mockImplementationOnce(() => { - return [bindingWithSecret]; - }); - ServiceCatalog.getServiceBrokers = jest.fn().mockImplementationOnce(() => { - return [broker]; - }); - ServiceCatalog.getServiceClasses = jest.fn().mockImplementationOnce(() => { - return [clusterClass]; - }); - ServiceCatalog.getServicePlans = jest.fn().mockImplementationOnce(() => { - return [servicePlan]; - }); - ServiceCatalog.deprovisionInstance = jest.fn(); - ServiceCatalog.syncBroker = jest.fn(); - boomFn = jest.fn().mockImplementationOnce(() => { - throw new Error("Boom!"); - }); - ServiceCatalog.isCatalogInstalled = jest.fn().mockImplementationOnce(() => true); -}); - -// Regular action creators -interface ITestCase { - name: string; - action: (...args: any[]) => any; - args?: any; - payload?: any; -} - -const actionTestCases: ITestCase[] = [ - { name: "checkCatalogInstall", action: catalogActions.checkCatalogInstall }, - { name: "installed", action: catalogActions.installed }, - { name: "notInstalled", action: catalogActions.notInstalled }, - { name: "requestBrokers", action: catalogActions.requestBrokers }, - { - name: "receiveBrokers", - action: catalogActions.receiveBrokers, - args: [[broker]], - payload: [broker], - }, - { name: "requestPlans", action: catalogActions.requestPlans }, - { - name: "receivePlans", - action: catalogActions.receivePlans, - args: [[servicePlan]], - payload: [servicePlan], - }, - { name: "requestInstances", action: catalogActions.requestInstances }, - { - name: "receiveInstances", - action: catalogActions.receiveInstances, - args: [[serviceInstance]], - payload: [serviceInstance], - }, - { name: "requestBindingsWithSecrets", action: catalogActions.requestBindingsWithSecrets }, - { - name: "receiveBindingsWithSecrets", - action: catalogActions.receiveBindingsWithSecrets, - args: [[bindingWithSecret]], - payload: [bindingWithSecret], - }, - { name: "requestClasses", action: catalogActions.requestClasses }, - { - name: "receiveClasses", - action: catalogActions.receiveClasses, - args: [[bindingWithSecret]], - payload: [bindingWithSecret], - }, - { - name: "errorCatalog", - action: catalogActions.errorCatalog, - args: [new Error("foo"), "create"], - payload: { err: new Error("foo"), op: "create" }, - }, -]; - -actionTestCases.forEach(tc => { - describe(tc.name, () => { - it("has expected structure", () => { - const actionResult = tc.args ? tc.action.call(null, ...tc.args) : tc.action.call(null); - expect(actionResult).toEqual({ - type: getType(tc.action), - payload: tc.payload, - }); - }); - }); -}); - -// Async action creators -describe("provision", () => { - const provisionCMD = catalogActions.provision( - testArgs.releaseName, - testArgs.namespace, - testArgs.className, - testArgs.planName, - testArgs.params, - ); - - it("calls ServiceInstance.create and returns true if no error", async () => { - const res = await store.dispatch(provisionCMD); - expect(res).toBe(true); - - expect(store.getActions().length).toBe(0); - expect(ServiceInstance.create).toHaveBeenCalledWith( - testArgs.kubeappsCluster, - testArgs.releaseName, - testArgs.namespace, - testArgs.className, - testArgs.planName, - {}, - ); - }); - - it("dispatches errorCatalog if error creating the instance", async () => { - ServiceInstance.create = boomFn; - - const expectedActions = [ - { - type: getType(catalogActions.errorCatalog), - payload: errorPayload("create"), - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - }); - - it("filters the submitted parameters if they are empty", async () => { - const params = { - a: 1, - f: { - g: [], - h: { - i: "", - }, - }, - j: { - k: { - l: "m", - }, - }, - }; - // It omits "f" because it's empty but not "a" or "j" - const expectedParams = { a: 1, j: { k: { l: "m" } } }; - const cmd = catalogActions.provision( - testArgs.releaseName, - testArgs.namespace, - testArgs.className, - testArgs.planName, - params, - ); - await store.dispatch(cmd); - expect(ServiceInstance.create).toHaveBeenCalledWith( - testArgs.kubeappsCluster, - testArgs.releaseName, - testArgs.namespace, - testArgs.className, - testArgs.planName, - expectedParams, - ); - }); -}); - -describe("deprovision", () => { - const provisionCMD = catalogActions.deprovision(serviceInstance); - - it("calls ServiceInstance.deprovisionInstance and returns true if no error", async () => { - const res = await store.dispatch(provisionCMD); - expect(res).toBe(true); - - expect(store.getActions().length).toBe(0); - expect(ServiceCatalog.deprovisionInstance).toHaveBeenCalledWith( - testArgs.kubeappsCluster, - serviceInstance, - ); - }); - - it("dispatches errorCatalog if error", async () => { - ServiceCatalog.deprovisionInstance = boomFn; - - const expectedActions = [ - { - type: getType(catalogActions.errorCatalog), - payload: { err: new Error("Boom!"), op: "deprovision" }, - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - }); -}); - -describe("addBinding", () => { - const provisionCMD = catalogActions.addBinding( - testArgs.bindingName, - testArgs.instanceName, - testArgs.namespace, - testArgs.params, - ); - - it("calls ServiceBinding.create and returns true if no error", async () => { - const res = await store.dispatch(provisionCMD); - expect(res).toBe(true); - - expect(store.getActions().length).toBe(0); - expect(ServiceBinding.create).toHaveBeenCalledWith( - testArgs.bindingName, - testArgs.instanceName, - testArgs.kubeappsCluster, - testArgs.namespace, - testArgs.params, - ); - }); - - it("dispatches errorCatalog if error", async () => { - ServiceBinding.create = boomFn; - - const expectedActions = [ - { - type: getType(catalogActions.errorCatalog), - payload: errorPayload("create"), - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - }); - - it("filters the submitted parameters if they are empty", async () => { - const params = { - a: 1, - b: { - c: [], - }, - f: { - g: [], - h: { - i: "", - }, - }, - j: { - k: { - l: "m", - }, - }, - }; - // It omits "f" because it's empty but not "a" or "j" - const expectedParams = { a: 1, j: { k: { l: "m" } } }; - const cmd = catalogActions.addBinding( - testArgs.bindingName, - testArgs.instanceName, - testArgs.namespace, - params, - ); - await store.dispatch(cmd); - expect(ServiceBinding.create).toHaveBeenCalledWith( - testArgs.bindingName, - testArgs.instanceName, - testArgs.kubeappsCluster, - testArgs.namespace, - expectedParams, - ); - }); -}); - -describe("removeBinding", () => { - const provisionCMD = catalogActions.removeBinding(testArgs.bindingName, testArgs.namespace); - - it("calls ServiceBinding.delete and returns true if no error", async () => { - const res = await store.dispatch(provisionCMD); - expect(res).toBe(true); - - expect(store.getActions().length).toBe(0); - expect(ServiceBinding.delete).toHaveBeenCalledWith( - testArgs.kubeappsCluster, - testArgs.namespace, - testArgs.bindingName, - ); - }); - - it("dispatches errorCatalog if error", async () => { - ServiceBinding.delete = boomFn; - - const expectedActions = [ - { - type: getType(catalogActions.errorCatalog), - payload: errorPayload("delete"), - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - }); -}); - -describe("sync", () => { - const provisionCMD = catalogActions.sync(broker); - - it("calls ServiceCatalog.syncBroker if no error", async () => { - await store.dispatch(provisionCMD); - expect(store.getActions().length).toBe(0); - expect(ServiceCatalog.syncBroker).toHaveBeenCalledWith(testArgs.kubeappsCluster, broker); - }); - - it("dispatches errorCatalog if error", async () => { - ServiceCatalog.syncBroker = boomFn; - - const expectedActions = [ - { - type: getType(catalogActions.errorCatalog), - payload: { err: new Error("Boom!"), op: "update" }, - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - }); -}); - -describe("getBindings", () => { - const provisionCMD = catalogActions.getBindings(testArgs.namespace); - - it("calls ServiceBinding.list and dispatches binding actions if no error", async () => { - const expectedActions = [ - { - type: getType(catalogActions.requestBindingsWithSecrets), - }, - { - type: getType(catalogActions.receiveBindingsWithSecrets), - payload: [bindingWithSecret], - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - expect(ServiceBinding.list).toHaveBeenCalledWith(testArgs.kubeappsCluster, testArgs.namespace); - }); - - it("dispatches requestBindingsWithSecrets and errorCatalog if error", async () => { - ServiceBinding.list = boomFn; - - const expectedActions = [ - { - type: getType(catalogActions.requestBindingsWithSecrets), - }, - { - type: getType(catalogActions.errorCatalog), - payload: errorPayload("fetch"), - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - }); -}); - -describe("getBrokers", () => { - const provisionCMD = catalogActions.getBrokers(); - - it("calls ServiceCatalog.getServiceBrokers and dispatches requestBrokers and receiveBroker if no error", async () => { - const expectedActions = [ - { - type: getType(catalogActions.requestBrokers), - }, - { - type: getType(catalogActions.receiveBrokers), - payload: [broker], - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - expect(ServiceCatalog.getServiceBrokers).toHaveBeenCalled(); - }); - - it("dispatches requestBrokers and errorCatalog if error", async () => { - ServiceCatalog.getServiceBrokers = boomFn; - - const expectedActions = [ - { - type: getType(catalogActions.requestBrokers), - }, - { - type: getType(catalogActions.errorCatalog), - payload: errorPayload("fetch"), - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - }); -}); - -describe("getClasses", () => { - const provisionCMD = catalogActions.getClasses(); - - it("calls ServiceCatalog.getServiceClasses and dispatches requestClasses and receiveClasses if no error", async () => { - const expectedActions = [ - { - type: getType(catalogActions.requestClasses), - }, - { - type: getType(catalogActions.receiveClasses), - payload: [clusterClass], - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - expect(ServiceCatalog.getServiceClasses).toHaveBeenCalled(); - }); - - it("dispatches requestClasses and errorCatalog if error", async () => { - ServiceCatalog.getServiceClasses = boomFn; - - const expectedActions = [ - { - type: getType(catalogActions.requestClasses), - }, - { - type: getType(catalogActions.errorCatalog), - payload: errorPayload("fetch"), - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - }); -}); - -describe("getInstances", () => { - const provisionCMD = catalogActions.getInstances(testArgs.namespace); - - it("calls ServiceInstance.list and dispatches requestInstances and receiveInstances if no error", async () => { - const expectedActions = [ - { - type: getType(catalogActions.requestInstances), - }, - { - type: getType(catalogActions.receiveInstances), - payload: [serviceInstance], - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - expect(ServiceInstance.list).toHaveBeenCalledWith(testArgs.kubeappsCluster, testArgs.namespace); - }); - - it("dispatches requestInstances and errorCatalog if error", async () => { - ServiceInstance.list = boomFn; - - const expectedActions = [ - { - type: getType(catalogActions.requestInstances), - }, - { - type: getType(catalogActions.errorCatalog), - payload: errorPayload("fetch"), - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - }); -}); - -describe("getPlans", () => { - const provisionCMD = catalogActions.getPlans(); - - it("calls ServiceCatalog.getServicePlans and dispatches requestPlans and receivePlans if no error", async () => { - const expectedActions = [ - { - type: getType(catalogActions.requestPlans), - }, - { - type: getType(catalogActions.receivePlans), - payload: [servicePlan], - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - expect(ServiceCatalog.getServicePlans).toHaveBeenCalled(); - }); - - it("dispatches requestPlans and errorCatalog if error", async () => { - ServiceCatalog.getServicePlans = boomFn; - - const expectedActions = [ - { - type: getType(catalogActions.requestPlans), - }, - { - type: getType(catalogActions.errorCatalog), - payload: errorPayload("fetch"), - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - }); -}); - -describe("checkCatalogInstalled", () => { - const provisionCMD = catalogActions.checkCatalogInstalled(); - - it("dispatches installed = true if installed", async () => { - const expectedActions = [ - { - type: getType(catalogActions.installed), - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - expect(ServiceCatalog.isCatalogInstalled).toHaveBeenCalled(); - }); - - it("dispatches installed = false otherwise", async () => { - ServiceCatalog.isCatalogInstalled = jest.fn().mockImplementationOnce(() => false); - - const expectedActions = [ - { - type: getType(catalogActions.notInstalled), - }, - ]; - - await store.dispatch(provisionCMD); - expect(store.getActions()).toEqual(expectedActions); - expect(ServiceCatalog.isCatalogInstalled).toHaveBeenCalled(); - }); -}); diff --git a/dashboard/src/actions/catalog.ts b/dashboard/src/actions/catalog.ts deleted file mode 100644 index b6eb649c0c1..00000000000 --- a/dashboard/src/actions/catalog.ts +++ /dev/null @@ -1,263 +0,0 @@ -import { ThunkAction } from "redux-thunk"; -import { IClusterServiceClass } from "shared/ClusterServiceClass"; -import { IServiceBindingWithSecret, ServiceBinding } from "shared/ServiceBinding"; -import { IServiceBroker, IServicePlan, ServiceCatalog } from "shared/ServiceCatalog"; -import { IServiceInstance, ServiceInstance } from "shared/ServiceInstance"; -import { IStoreState } from "shared/types"; -import { ActionType, deprecated } from "typesafe-actions"; -import helpers from "./helpers"; - -const { createAction } = deprecated; - -export const checkCatalogInstall = createAction("CHECK_INSTALL"); -export const installed = createAction("INSTALLED"); -export const notInstalled = createAction("NOT_INSTALLED"); -export const requestBrokers = createAction("REQUEST_BROKERS"); -export const receiveBrokers = createAction("RECEIVE_BROKERS", resolve => { - return (brokers: IServiceBroker[]) => resolve(brokers); -}); - -export const requestPlans = createAction("REQUEST_PLANS"); -export const receivePlans = createAction("RECEIVE_PLANS", resolve => { - return (plans: IServicePlan[]) => resolve(plans); -}); - -export const requestInstances = createAction("REQUEST_INSTANCES"); -export const receiveInstances = createAction("RECEIVE_INSTANCES", resolve => { - return (instances: IServiceInstance[]) => resolve(instances); -}); - -export const requestBindingsWithSecrets = createAction("REQUEST_BINDINGS_WITH_SECRETS"); -export const receiveBindingsWithSecrets = createAction("RECEIVE_BINDINGS_WITH_SECRETS", resolve => { - return (bindingsWithSecrets: IServiceBindingWithSecret[]) => resolve(bindingsWithSecrets); -}); - -export const requestClasses = createAction("REQUEST_PLANS"); -export const receiveClasses = createAction("RECEIVE_CLASSES", resolve => { - return (classes: IClusterServiceClass[]) => resolve(classes); -}); - -export const errorCatalog = createAction("ERROR_CATALOG", resolve => { - return (err: Error, op: "fetch" | "create" | "delete" | "deprovision" | "update") => - resolve({ err, op }); -}); - -const actions = [ - checkCatalogInstall, - installed, - notInstalled, - requestBrokers, - receiveBrokers, - requestPlans, - receivePlans, - requestInstances, - receiveInstances, - requestBindingsWithSecrets, - receiveBindingsWithSecrets, - requestClasses, - receiveClasses, - errorCatalog, -]; - -export type ServiceCatalogAction = ActionType; - -export function provision( - releaseName: string, - namespace: string, - className: string, - planName: string, - parameters: {}, -): ThunkAction, IStoreState, null, ServiceCatalogAction> { - return async (dispatch, getState) => { - const { - clusters: { currentCluster }, - } = getState(); - try { - const filteredParams = helpers.object.removeEmptyFields(parameters); - await ServiceInstance.create( - currentCluster, - releaseName, - namespace, - className, - planName, - filteredParams, - ); - return true; - } catch (e: any) { - dispatch(errorCatalog(e, "create")); - return false; - } - }; -} - -export function addBinding( - bindingName: string, - instanceName: string, - namespace: string, - parameters: {}, -): ThunkAction, IStoreState, null, ServiceCatalogAction> { - return async (dispatch, getState) => { - const { - clusters: { currentCluster }, - } = getState(); - try { - const filteredParams = helpers.object.removeEmptyFields(parameters); - await ServiceBinding.create( - bindingName, - instanceName, - currentCluster, - namespace, - filteredParams, - ); - return true; - } catch (e: any) { - dispatch(errorCatalog(e, "create")); - return false; - } - }; -} - -export function removeBinding( - name: string, - namespace: string, -): ThunkAction, IStoreState, null, ServiceCatalogAction> { - return async (dispatch, getState) => { - const { - clusters: { currentCluster }, - } = getState(); - try { - await ServiceBinding.delete(currentCluster, namespace, name); - return true; - } catch (e: any) { - dispatch(errorCatalog(e, "delete")); - return false; - } - }; -} - -export function deprovision( - instance: IServiceInstance, -): ThunkAction, IStoreState, null, ServiceCatalogAction> { - return async (dispatch, getState) => { - const { - clusters: { currentCluster }, - } = getState(); - try { - await ServiceCatalog.deprovisionInstance(currentCluster, instance); - return true; - } catch (e: any) { - dispatch(errorCatalog(e, "deprovision")); - return false; - } - }; -} - -export function sync( - broker: IServiceBroker, -): ThunkAction, IStoreState, null, ServiceCatalogAction> { - return async (dispatch, getState) => { - const { - config: { kubeappsCluster }, - } = getState(); - try { - await ServiceCatalog.syncBroker(kubeappsCluster, broker); - } catch (e: any) { - dispatch(errorCatalog(e, "update")); - } - }; -} - -export function getBindings( - ns?: string, -): ThunkAction, IStoreState, null, ServiceCatalogAction> { - return async (dispatch, getState) => { - const { - config: { kubeappsCluster }, - } = getState(); - dispatch(requestBindingsWithSecrets()); - try { - const bindingsWithSecrets = await ServiceBinding.list(kubeappsCluster, ns); - dispatch(receiveBindingsWithSecrets(bindingsWithSecrets)); - } catch (e: any) { - dispatch(errorCatalog(e, "fetch")); - } - }; -} - -export function getBrokers(): ThunkAction, IStoreState, null, ServiceCatalogAction> { - return async (dispatch, getState) => { - const { - clusters: { currentCluster }, - } = getState(); - dispatch(requestBrokers()); - try { - const brokers = await ServiceCatalog.getServiceBrokers(currentCluster); - dispatch(receiveBrokers(brokers)); - } catch (e: any) { - dispatch(errorCatalog(e, "fetch")); - } - }; -} - -export function getClasses(): ThunkAction, IStoreState, null, ServiceCatalogAction> { - return async (dispatch, getState) => { - const { - clusters: { currentCluster }, - } = getState(); - dispatch(requestClasses()); - try { - const classes = await ServiceCatalog.getServiceClasses(currentCluster); - dispatch(receiveClasses(classes)); - } catch (e: any) { - dispatch(errorCatalog(e, "fetch")); - } - }; -} - -export function getInstances( - ns?: string, -): ThunkAction, IStoreState, null, ServiceCatalogAction> { - return async (dispatch, getState) => { - const { - clusters: { currentCluster }, - } = getState(); - dispatch(requestInstances()); - try { - const instances = await ServiceInstance.list(currentCluster, ns); - dispatch(receiveInstances(instances)); - } catch (e: any) { - dispatch(errorCatalog(e, "fetch")); - } - }; -} - -export function getPlans(): ThunkAction, IStoreState, null, ServiceCatalogAction> { - return async (dispatch, getState) => { - const { - clusters: { currentCluster }, - } = getState(); - dispatch(requestPlans()); - try { - const plans = await ServiceCatalog.getServicePlans(currentCluster); - dispatch(receivePlans(plans)); - } catch (e: any) { - dispatch(errorCatalog(e, "fetch")); - } - }; -} - -export function checkCatalogInstalled(): ThunkAction< - Promise, - IStoreState, - null, - ServiceCatalogAction -> { - return async (dispatch, getState) => { - const { - clusters: { currentCluster }, - } = getState(); - const isServiceCatalogInstalled = await ServiceCatalog.isCatalogInstalled(currentCluster); - isServiceCatalogInstalled ? dispatch(installed()) : dispatch(notInstalled()); - return isServiceCatalogInstalled; - }; -} diff --git a/dashboard/src/actions/index.ts b/dashboard/src/actions/index.ts index a322f900006..817febee536 100644 --- a/dashboard/src/actions/index.ts +++ b/dashboard/src/actions/index.ts @@ -1,7 +1,6 @@ import { push } from "connected-react-router"; import * as apps from "./apps"; import * as auth from "./auth"; -import * as catalog from "./catalog"; import * as charts from "./charts"; import * as config from "./config"; import * as kube from "./kube"; @@ -12,7 +11,6 @@ import * as repos from "./repos"; export default { apps, auth, - catalog, charts, config, kube, diff --git a/dashboard/src/shared/ClusterServiceClass.ts b/dashboard/src/shared/ClusterServiceClass.ts deleted file mode 100644 index 4366d219757..00000000000 --- a/dashboard/src/shared/ClusterServiceClass.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { axiosWithAuth } from "./AxiosInstance"; -import { APIBase } from "./Kube"; -import { ServiceCatalog } from "./ServiceCatalog"; - -export interface IClusterServiceClass { - metadata: { - creationTimestamp: string; - name: string; - resourceVersion: string; - selfLink: string; - uid: string; - }; - spec: { - bindable: boolean; - binding_retrievable: boolean; - clusterServiceBrokerName: string; - description: string; - externalID: string; - externalName: string; - planUpdatable: boolean; - tags: string[]; - externalMetadata?: { - displayName: string; - documentationUrl: string; - imageUrl: string; - longDescription: string; - supportUrl: string; - }; - }; - status: { - removedFromBrokerCatalog: boolean; - }; -} - -export class ClusterServiceClass { - public static async get( - cluster: string, - namespace?: string, - name?: string, - ): Promise { - const url = this.getLink(cluster, namespace, name); - const { data } = await axiosWithAuth.get(url); - return data; - } - - public static async list(cluster: string): Promise { - const instances = await ServiceCatalog.getItems( - cluster, - "serviceinstances", - ); - return instances; - } - - private static getLink(cluster: string, namespace?: string, name?: string): string { - return `${APIBase(cluster)}/apis/servicecatalog.k8s.io/v1beta1${ - namespace ? `/namespaces/${namespace}` : "" - }/clusterserviceclasses${name ? `/${name}` : ""}`; - } -} diff --git a/dashboard/src/shared/ServiceBinding.ts b/dashboard/src/shared/ServiceBinding.ts deleted file mode 100644 index 5480d6fc416..00000000000 --- a/dashboard/src/shared/ServiceBinding.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { axiosWithAuth } from "./AxiosInstance"; -import { APIBase } from "./Kube"; -import { ICondition, ServiceCatalog } from "./ServiceCatalog"; -import * as url from "./url"; - -interface IK8sApiSecretResponse { - kind: string; - apiVersion: string; - metadata: { - selfLink: string; - resourceVersion: string; - }; - data: { [s: string]: string }; -} - -interface IServiceBinding { - metadata: { - name: string; - selfLink: string; - uid: string; - resourceVersion: string; - creationTimestamp: string; - finalizers: string[]; - generation: number; - namespace: string; - }; - spec: { - externalID: string; - instanceRef: { - name: string; - }; - secretName: string; - }; - status: { - conditions: ICondition[]; - asyncOpInProgress: boolean; - currentOperation: string; - reconciledGeneration: number; - operationStartTime: string; - externalProperties: {}; - orphanMitigationInProgress: boolean; - unbindStatus: string; - }; -} - -export interface IServiceBindingWithSecret { - binding: IServiceBinding; - secret?: IK8sApiSecretResponse; -} - -export class ServiceBinding { - public static async create( - bindingName: string, - instanceRefName: string, - cluster: string, - namespace: string, - parameters: {}, - ) { - const u = ServiceBinding.getLink(cluster, namespace); - const { data } = await axiosWithAuth.post(u, { - apiVersion: "servicecatalog.k8s.io/v1beta1", - kind: "ServiceBinding", - metadata: { - name: bindingName, - }, - spec: { - instanceRef: { - name: instanceRefName, - }, - parameters, - }, - }); - return data; - } - - public static async delete(cluster: string, namespace: string, name: string) { - const u = this.getLink(cluster, namespace, name); - return axiosWithAuth.delete(u); - } - - public static async get(cluster: string, namespace: string, name: string) { - const u = this.getLink(cluster, namespace, name); - const { data } = await axiosWithAuth.get(u); - return data; - } - - public static async list( - cluster: string, - namespace?: string, - ): Promise { - const bindings = await ServiceCatalog.getItems( - cluster, - "servicebindings", - namespace, - ); - - return Promise.all( - bindings.map(binding => { - const { secretName } = binding.spec; - const ns = binding.metadata.namespace; - return axiosWithAuth - .get(url.api.k8s.secret(cluster, ns, secretName)) - .then(response => { - return { binding, secret: response.data }; - }) - .catch(() => { - // return with undefined secrets - return { binding }; - }); - }), - ); - } - - private static getLink(cluster: string, namespace?: string, name?: string): string { - return `${APIBase(cluster)}/apis/servicecatalog.k8s.io/v1beta1${ - namespace ? `/namespaces/${namespace}` : "" - }/servicebindings${name ? `/${name}` : ""}`; - } -} diff --git a/dashboard/src/shared/ServiceCatalog.ts b/dashboard/src/shared/ServiceCatalog.ts deleted file mode 100644 index 256d1258006..00000000000 --- a/dashboard/src/shared/ServiceCatalog.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { JSONSchema6 } from "json-schema"; -import * as url from "shared/url"; -import { axiosWithAuth } from "./AxiosInstance"; -import { IClusterServiceClass } from "./ClusterServiceClass"; -import { APIBase } from "./Kube"; -import { IServiceInstance } from "./ServiceInstance"; -import { IK8sList, IStatus } from "./types"; - -export class ServiceCatalog { - public static async getServiceClasses(cluster: string) { - return this.getItems(cluster, "clusterserviceclasses"); - } - - public static async getServiceBrokers(cluster: string) { - return this.getItems(cluster, "clusterservicebrokers"); - } - - public static async getServicePlans(cluster: string) { - return this.getItems(cluster, "clusterserviceplans"); - } - - public static async deprovisionInstance(cluster: string, instance: IServiceInstance) { - const { data } = await axiosWithAuth.delete(`${APIBase(cluster)}${instance.metadata.selfLink}`); - return data; - } - - public static async syncBroker(cluster: string, broker: IServiceBroker) { - const { data } = await axiosWithAuth.patch( - url.api.k8s.clusterservicebrokers.sync(cluster, broker), - { - spec: { - relistRequests: broker.spec.relistRequests + 1, - }, - }, - { - headers: { "Content-Type": "application/merge-patch+json" }, - validateStatus: () => true, - }, - ); - return data; - } - - public static async isCatalogInstalled(cluster: string): Promise { - try { - const { status } = await axiosWithAuth.get(this.endpoint(cluster)); - return status === 200; - } catch (e: any) { - return false; - } - } - - public static async getItems( - cluster: string, - resource: string, - namespace?: string, - ): Promise { - const response = await axiosWithAuth.get>( - this.endpoint(cluster) + (namespace ? `/namespaces/${namespace}` : "") + `/${resource}`, - ); - const json = response.data; - return json.items; - } - - private static endpoint(cluster: string): string { - return `${APIBase(cluster)}/apis/servicecatalog.k8s.io/v1beta1`; - } -} -export interface IK8sApiListResponse { - kind: string; - apiVersion: string; - metadata: { - selfLink: string; - resourceVersion: string; - }; - items: T[]; -} - -export interface ICondition { - type: string; - status: string; - lastTransitionTime: string; - reason: string; - message: string; -} - -export interface IServiceBroker { - metadata: { - name: string; - selfLink: string; - uid: string; - resourceVersion: string; - generation: number; - creationTimestamp: string; - finalizers: string[]; - }; - spec: { - url: string; - authInfo: any; // Look into - relistBehavior: string; - relistDuration: string; - relistRequests: number; - }; - status: { - conditions: ICondition[]; - reconciledGeneration: number; - lastCatalogRetrievalTime: string; - }; -} - -export interface IServicePlan { - metadata: { - name: string; - selfLink: string; - uid: string; - resourceVersion: string; - creationTimestamp: string; - }; - spec: { - clusterServiceBrokerName: string; - externalName: string; - externalID: string; - description: string; - externalMetadata?: { - displayName: string; - bullets: string[]; - }; - instanceCreateParameterSchema?: JSONSchema6; - serviceBindingCreateParameterSchema?: JSONSchema6; - free: boolean; - clusterServiceClassRef: { - name: string; - }; - }; - status: { - removedFromBrokerCatalog: boolean; - }; -} diff --git a/dashboard/src/shared/ServiceInstance.ts b/dashboard/src/shared/ServiceInstance.ts deleted file mode 100644 index 55f62ddbc58..00000000000 --- a/dashboard/src/shared/ServiceInstance.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { axiosWithAuth } from "./AxiosInstance"; -import { APIBase } from "./Kube"; -import { ICondition, ServiceCatalog } from "./ServiceCatalog"; -import { IStatus } from "./types"; - -export interface IServiceInstance { - metadata: { - name: string; - namespace: string; - selfLink: string; - uid: string; - resourceVersion: string; - creationTimestamp: string; - finalizers: string[]; - generation: number; - }; - spec: { - clusterServiceClassExternalName: string; - clusterServicePlanExternalName: string; - externalID: string; - clusterServicePlanRef?: { - name: string; - }; - clusterServiceClassRef?: { - name: string; - }; - }; - status: { conditions: ICondition[] }; -} - -export class ServiceInstance { - public static async create( - cluster: string, - releaseName: string, - namespace: string, - className: string, - planName: string, - parameters: {}, - ) { - const { data } = await axiosWithAuth.post(this.getLink(cluster, namespace), { - apiVersion: "servicecatalog.k8s.io/v1beta1", - kind: "ServiceInstance", - metadata: { - name: releaseName, - }, - spec: { - clusterServiceClassExternalName: className, - clusterServicePlanExternalName: planName, - parameters, - }, - }); - return data; - } - - public static async get( - cluster: string, - namespace?: string, - name?: string, - ): Promise { - const url = this.getLink(cluster, namespace, name); - const { data } = await axiosWithAuth.get(url); - return data; - } - - public static async list(cluster: string, namespace?: string): Promise { - const instances = await ServiceCatalog.getItems( - cluster, - "serviceinstances", - namespace, - ); - return instances; - } - - private static getLink(cluster: string, namespace?: string, name?: string): string { - return `${APIBase(cluster)}/apis/servicecatalog.k8s.io/v1beta1${ - namespace ? `/namespaces/${namespace}` : "" - }/serviceinstances${name ? `/${name}` : ""}`; - } -} diff --git a/dashboard/src/shared/url.ts b/dashboard/src/shared/url.ts index 336838ef368..073784da229 100644 --- a/dashboard/src/shared/url.ts +++ b/dashboard/src/shared/url.ts @@ -3,7 +3,6 @@ import { InstalledPackageReference, } from "gen/kubeappsapis/core/packages/v1alpha1/packages"; import { Plugin } from "gen/kubeappsapis/core/plugins/v1alpha1/plugins"; -import { IServiceBroker } from "./ServiceCatalog"; import { IRepo } from "./types"; export const app = { @@ -128,13 +127,6 @@ export const api = { namespaces: (cluster: string) => `${api.k8s.base(cluster)}/api/v1/namespaces`, namespace: (cluster: string, namespace: string) => namespace ? `${api.k8s.namespaces(cluster)}/${namespace}` : `${api.k8s.base(cluster)}/api/v1`, - // clusterservicebrokers and operators operate on the default cluster only, currently. - clusterservicebrokers: { - sync: (cluster: string, broker: IServiceBroker) => - `${api.k8s.base(cluster)}/apis/servicecatalog.k8s.io/v1beta1/clusterservicebrokers/${ - broker.metadata.name - }`, - }, operators: { operators: (cluster: string, namespace: string) => `${api.k8s.base(cluster)}/apis/packages.operators.coreos.com/v1/${withNS(