Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add minor improvements prior to the repos UI #4848

Merged
merged 6 commits into from
Jun 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/kubeapps-apis/core/packages/v1alpha1/packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func NewPackagesServer(pkgingPlugins []pluginsv1alpha1.PluginWithServer) (*packa
plugin: p.Plugin,
server: pkgsSrv,
}
log.Infof("Registered %v for core.packaging.v1alpha1 aggregation.", p.Plugin)
log.Infof("Registered %v for core.packaging.v1alpha1 packages aggregation.", p.Plugin)
}
return &packagesServer{
pluginsWithServers: pluginsWithServer,
Expand Down
2 changes: 1 addition & 1 deletion cmd/kubeapps-apis/core/packages/v1alpha1/repositories.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func NewRepositoriesServer(pkgingPlugins []pluginsv1alpha1.PluginWithServer) (*r
plugin: p.Plugin,
server: pkgsSrv,
}
log.Infof("Registered %v for core.packaging.v1alpha1 aggregation.", p.Plugin)
log.Infof("Registered %v for core.packaging.v1alpha1 repositories aggregation.", p.Plugin)
}
return &repositoriesServer{
pluginsWithServers: pluginsWithServer,
Expand Down
5 changes: 4 additions & 1 deletion dashboard/src/actions/namespace.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,10 @@ describe("setNamespace", () => {

describe("canCreate", () => {
it("checks if it can create namespaces", async () => {
Kube.canI = jest.fn().mockReturnValue(true);
Kube.canI = jest.fn().mockReturnValue({
then: jest.fn(f => f(true)),
catch: jest.fn(f => f(false)),
});
const expectedActions = [
{
type: getType(setAllowCreate),
Expand Down
2 changes: 2 additions & 0 deletions dashboard/src/components/AppList/AppList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ beforeEach(() => {
spyOnUseDispatch = jest.spyOn(ReactRedux, "useDispatch").mockReturnValue(mockDispatch);
Kube.canI = jest.fn().mockReturnValue({
then: jest.fn(f => f(true)),
catch: jest.fn(f => f(false)),
});
});

Expand Down Expand Up @@ -126,6 +127,7 @@ context("when changing props", () => {
it("should hide the all-namespace switch if the user doesn't have permissions", async () => {
Kube.canI = jest.fn().mockReturnValue({
then: jest.fn((f: any) => f(false)),
catch: jest.fn(f => f(false)),
});
const wrapper = mountWrapper(defaultStore, <AppList />);
expect(wrapper.find("input[type='checkbox']")).not.toExist();
Expand Down
4 changes: 3 additions & 1 deletion dashboard/src/components/AppList/AppList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ function AppList() {
useEffect(() => {
// In order to be able to list applications in all namespaces, it's necessary to be able
// to list/get secrets in all of them.
Kube.canI(cluster, "", "secrets", "list", "").then(allowed => setCanSetAllNS(allowed));
Kube.canI(cluster, "", "secrets", "list", "")
.then(allowed => setCanSetAllNS(allowed))
?.catch(() => setCanSetAllNS(false));
}, [cluster]);

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import {
InstalledPackageDetail,
AvailablePackageDetail,
ResourceRef,
} from "gen/kubeappsapis/core/packages/v1alpha1/packages";
import { getStore, mountWrapper } from "shared/specs/mountWrapper";
import CustomAppView from ".";
Expand All @@ -21,7 +22,7 @@ const defaultProps = {
},
} as InstalledPackageDetail,
resourceRefs: {
ingresses: [],
ingresses: [] as ResourceRef[],
deployments: [
{
cluster: "default",
Expand All @@ -31,10 +32,10 @@ const defaultProps = {
namespaced: true,
name: "ssh-server-example",
namespace: "demo-namespace",
},
],
statefulsets: [],
daemonsets: [],
} as ResourceRef,
] as ResourceRef[],
statefulsets: [] as ResourceRef[],
daemonsets: [] as ResourceRef[],
otherResources: [
{
cluster: "default",
Expand All @@ -44,8 +45,8 @@ const defaultProps = {
namespaced: true,
name: "ssh-server-example-root-pv-claim",
namespace: "demo-namespace",
},
],
} as ResourceRef,
] as ResourceRef[],
services: [
{
cluster: "default",
Expand All @@ -55,10 +56,10 @@ const defaultProps = {
namespaced: true,
name: "ssh-server-example",
namespace: "demo-namespace",
},
],
secrets: [],
} as unknown as IAppViewResourceRefs,
} as ResourceRef,
] as ResourceRef[],
secrets: [] as ResourceRef[],
} as IAppViewResourceRefs,
appDetails: {} as AvailablePackageDetail,
};

Expand Down
8 changes: 7 additions & 1 deletion dashboard/src/components/Catalog/CatalogItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,13 @@ export default function CatalogItems({
? []
: packageItems
.concat(crdItems)
.sort((a, b) => (a.item.name.toLowerCase() > b.item.name.toLowerCase() ? 1 : -1));
.sort((a, b) =>
a.item.name.toLowerCase() > b.item.name.toLowerCase()
? 1
: b.item.name.toLowerCase() > a.item.name.toLowerCase()
? -1
: 0,
);

if (hasFinishedFetching && sortedItems.length === 0) {
return <p>No application matches the current filter.</p>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ beforeEach(() => {
spyOnUseDispatch = jest.spyOn(ReactRedux, "useDispatch").mockReturnValue(mockDispatch);
Kube.canI = jest.fn().mockReturnValue({
then: jest.fn(f => f(true)),
catch: jest.fn(f => f(false)),
});
});

Expand Down Expand Up @@ -76,6 +77,7 @@ it("fetches repos from all namespaces (without kubeappsNamespace)", () => {
it("should hide the all-namespace switch if the user doesn't have permissions", async () => {
Kube.canI = jest.fn().mockReturnValue({
then: jest.fn((f: any) => f(false)),
catch: jest.fn(f => f(false)),
});
const wrapper = mountWrapper(defaultStore, <AppRepoList />);
expect(wrapper.find("input[type='checkbox']")).not.toExist();
Expand Down Expand Up @@ -162,6 +164,7 @@ describe("global and namespaced repositories", () => {
it("shows the global repositories with the buttons deactivated if the current user is not allowed to modify them", () => {
Kube.canI = jest.fn().mockReturnValue({
then: jest.fn((f: any) => f(false)),
catch: jest.fn(f => f(false)),
});
const wrapper = mountWrapper(
getStore({
Expand Down
16 changes: 6 additions & 10 deletions dashboard/src/components/Config/AppRepoList/AppRepoList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,12 @@ function AppRepoList() {
}, [allNS, currentNamespace]);

useEffect(() => {
Kube.canI(cluster, "kubeapps.com", "apprepositories", "list", "").then(allowed =>
setCanSetAllNS(allowed),
);
Kube.canI(
kubeappsCluster,
"kubeapps.com",
"apprepositories",
"update",
globalReposNamespace,
).then(allowed => setCanEditGlobalRepos(allowed));
Kube.canI(cluster, "kubeapps.com", "apprepositories", "list", "")
.then(allowed => setCanSetAllNS(allowed))
?.catch(() => setCanSetAllNS(false));
Kube.canI(kubeappsCluster, "kubeapps.com", "apprepositories", "update", globalReposNamespace)
.then(allowed => setCanEditGlobalRepos(allowed))
?.catch(() => setCanEditGlobalRepos(false));
}, [cluster, kubeappsCluster, kubeappsNamespace, globalReposNamespace]);

const globalRepos: IAppRepository[] = [];
Expand Down
12 changes: 10 additions & 2 deletions dashboard/src/shared/KubeappsGrpcClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,26 @@ describe("kubeapps grpc client creation", () => {
const serviceClients = [
kubeappsGrpcClient.getPluginsServiceClientImpl(),
kubeappsGrpcClient.getPackagesServiceClientImpl(),
kubeappsGrpcClient.getRepositoriesServiceClientImpl(),
kubeappsGrpcClient.getResourcesServiceClientImpl(),
];
serviceClients.every(sc => expect(sc).not.toBeNull());
});

it("should create the clients for each plugin service", async () => {
const kubeappsGrpcClient = new KubeappsGrpcClient(fakeEmpyTransport);
const serviceClients = [
const packagesServiceClients = [
kubeappsGrpcClient.getHelmPackagesServiceClientImpl(),
kubeappsGrpcClient.getKappControllerPackagesServiceClientImpl(),
kubeappsGrpcClient.getFluxv2PackagesServiceClientImpl(),
];
serviceClients.every(sc => expect(sc).not.toBeNull());
const repositoriesServiceClients = [
kubeappsGrpcClient.getHelmRepositoriesServiceClientImpl(),
kubeappsGrpcClient.getKappControllerRepositoriesServiceClientImpl(),
kubeappsGrpcClient.getFluxV2RepositoriesServiceClientImpl(),
];
packagesServiceClients.every(sc => expect(sc).not.toBeNull());
repositoriesServiceClients.every(sc => expect(sc).not.toBeNull());
});
});

Expand Down
36 changes: 31 additions & 5 deletions dashboard/src/shared/KubeappsGrpcClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,20 @@

import { grpc } from "@improbable-eng/grpc-web";
import { PackagesServiceClientImpl } from "gen/kubeappsapis/core/packages/v1alpha1/packages";
import { RepositoriesServiceClientImpl } from "gen/kubeappsapis/core/packages/v1alpha1/repositories";
import { PluginsServiceClientImpl } from "gen/kubeappsapis/core/plugins/v1alpha1/plugins";
import { FluxV2PackagesServiceClientImpl } from "gen/kubeappsapis/plugins/fluxv2/packages/v1alpha1/fluxv2";
import { HelmPackagesServiceClientImpl } from "gen/kubeappsapis/plugins/helm/packages/v1alpha1/helm";
import { KappControllerPackagesServiceClientImpl } from "gen/kubeappsapis/plugins/kapp_controller/packages/v1alpha1/kapp_controller";
import {
FluxV2PackagesServiceClientImpl,
FluxV2RepositoriesServiceClientImpl,
} from "gen/kubeappsapis/plugins/fluxv2/packages/v1alpha1/fluxv2";
import {
HelmPackagesServiceClientImpl,
HelmRepositoriesServiceClientImpl,
} from "gen/kubeappsapis/plugins/helm/packages/v1alpha1/helm";
import {
KappControllerPackagesServiceClientImpl,
KappControllerRepositoriesServiceClientImpl,
} from "gen/kubeappsapis/plugins/kapp_controller/packages/v1alpha1/kapp_controller";
import {
GrpcWebImpl,
ResourcesServiceClientImpl,
Expand Down Expand Up @@ -46,6 +56,10 @@ export class KubeappsGrpcClient {
return new PackagesServiceClientImpl(this.getGrpcClient());
}

public getRepositoriesServiceClientImpl() {
return new RepositoriesServiceClientImpl(this.getGrpcClient());
}

public getPluginsServiceClientImpl() {
return new PluginsServiceClientImpl(this.getGrpcClient());
}
Expand All @@ -59,19 +73,31 @@ export class KubeappsGrpcClient {
return new ResourcesServiceClientImpl(this.getGrpcClient(token));
}

// Plugins (packages) APIs
// Plugins (packages/repositories) APIs
// TODO(agamez): ideally, these clients should be loaded automatically from a list of configured plugins

// Helm
public getHelmPackagesServiceClientImpl() {
return new HelmPackagesServiceClientImpl(this.getGrpcClient());
}
public getHelmRepositoriesServiceClientImpl() {
return new HelmRepositoriesServiceClientImpl(this.getGrpcClient());
}

// KappController
public getKappControllerPackagesServiceClientImpl() {
return new KappControllerPackagesServiceClientImpl(this.getGrpcClient());
}

public getKappControllerRepositoriesServiceClientImpl() {
return new KappControllerRepositoriesServiceClientImpl(this.getGrpcClient());
}
// Fluxv2
public getFluxv2PackagesServiceClientImpl() {
return new FluxV2PackagesServiceClientImpl(this.getGrpcClient());
}
public getFluxV2RepositoriesServiceClientImpl() {
return new FluxV2RepositoriesServiceClientImpl(this.getGrpcClient());
}
}

export default KubeappsGrpcClient;
8 changes: 6 additions & 2 deletions dashboard/src/shared/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,18 @@ export function getPluginName(plugin?: Plugin | string) {
}
}

export function getPluginPackageName(plugin?: Plugin | string) {
export function getPluginPackageName(plugin?: Plugin | PluginNames | string) {
// Temporary case while operators are not supported as kubeapps apis plugin
if (typeof plugin === "string") {
switch (plugin) {
case "chart":
return "Helm Chart";
case "helm":
case PluginNames.PACKAGES_HELM:
return "Helm Chart";
case PluginNames.PACKAGES_FLUX:
return "Helm Chart via Flux";
case PluginNames.PACKAGES_KAPP:
return "Carvel Package";
case "operator":
return "Operator";
default:
Expand Down