Skip to content

Commit

Permalink
store/cockpitApi: scan for blueprint files
Browse files Browse the repository at this point in the history
Add an initial commit to scan a preset directory for user blueprint
files. This makes use of the cockpit files api.
  • Loading branch information
kingsleyzissou authored and lucasgarfield committed Dec 12, 2024
1 parent d06346c commit 5cca844
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 10 deletions.
3 changes: 3 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,6 @@ export const PAGINATION_OFFSET = 0;
export const PAGINATION_LIMIT = 10;
export const PAGINATION_COUNT = 0;
export const SEARCH_INPUT = '';

export const BLUEPRINTS_DIR =
'.local/share/cockpit/image-builder-frontend/blueprints';
44 changes: 44 additions & 0 deletions src/mocks/cockpit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* eslint-disable @typescript-eslint/no-unused-vars */

// TODO: maybe we should pull in the cockpit types here
// and keep them in the project. Not ideal because it may
// diverge, so we need to think about it.
export interface UserInfo {
home: string;
}

export default {
user: (): Promise<UserInfo> => {
return new Promise((resolve) => {
resolve({
home: '',
});
});
},
file: (path: string) => {
return {
read: (): Promise<string> => {
return new Promise((resolve) => {
resolve('');
});
},
close: () => {},
};
},
};

export interface FileInfo {
entries?: Record<string, FileInfo>;
}

export const fsinfo = (
path: string,
attributes: (keyof FileInfo)[],
options: object
): Promise<FileInfo> => {
return new Promise((resolve) => {
resolve({
entries: {},
});
});
};
62 changes: 52 additions & 10 deletions src/store/cockpitApi.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
import TOML from '@ltd/j-toml';
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import cockpit from 'cockpit';
import { fsinfo } from 'fsinfo';

import {
GetArchitecturesApiResponse,
GetArchitecturesApiArg,
GetBlueprintsApiArg,
GetBlueprintsApiResponse,
BlueprintItem,
} from './imageBuilderApi';

import { BLUEPRINTS_DIR } from '../constants';

const emptyCockpitApi = createApi({
reducerPath: 'cockpitApi',
baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
endpoints: () => ({}),
});

const getBlueprintsPath = async () => {
const user = await cockpit.user();

// we will use the user's `.local` directory
// to save blueprints used for on-prem
return `${user.home}/${BLUEPRINTS_DIR}`;
};

export const cockpitApi = emptyCockpitApi.injectEndpoints({
endpoints: (builder) => {
return {
Expand All @@ -28,22 +42,50 @@ export const cockpitApi = emptyCockpitApi.injectEndpoints({
GetBlueprintsApiResponse,
GetBlueprintsApiArg
>({
queryFn: () => {
// TODO: Add cockpit file api support for reading in blueprints.
// For now we're just hardcoding a dummy response
// so we can render an empty table.
return new Promise((resolve) => {
resolve({
queryFn: async () => {
try {
const path = await getBlueprintsPath();

// we probably don't need any more information other
// than the entries from the directory
const info = await fsinfo(path, ['entries'], {
superuser: 'try',
});

const entries = Object.entries(info?.entries || {});
const blueprints: BlueprintItem[] = await Promise.all(
entries.map(async ([filename]) => {
const file = cockpit.file(`${path}/${filename}`);

const contents = await file.read();
const parsed = TOML.parse(contents);
file.close();

// TODO: add other blueprint options
return {
name: parsed.name as string,
id: filename as string,
version: parsed.version as number,
description: parsed.description as string,
last_modified_at: Date.now().toString(),
};
})
);

return {
data: {
meta: { count: 0 },
meta: { count: blueprints.length },
links: {
// TODO: figure out the pagination
first: '',
last: '',
},
data: [],
data: blueprints,
},
});
});
};
} catch (error) {
return { error };
}
},
}),
};
Expand Down
22 changes: 22 additions & 0 deletions src/test/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,28 @@ vi.mock('@unleash/proxy-client-react', () => ({
}),
}));

vi.mock(import('cockpit'), async () => {
return {
user: () => {
new Promise((resolve) => {
resolve({
home: '/home/osbuild',
});
});
},
};
});

vi.mock(import('fsinfo'), async () => {
return {
fsinfo: () => {
new Promise((resolve) => {
resolve({});
});
},
};
});

// Remove DOM dump from the testing-library output
configure({
getElementError: (message: string) => {
Expand Down
8 changes: 8 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@
"paths": {
"*": [
"./pkg/lib/*"
],
"cockpit": [
"./src/mocks/cockpit.ts",
"./pkg/lib/cockpit.ts"
],
"fsinfo": [
"./src/mocks/cockpit.ts",
"./pkg/lib/cockpit/fsinfo.ts"
]
}
}
Expand Down
5 changes: 5 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import react from '@vitejs/plugin-react';
import path from 'path';

const config = {
plugins: [react()],
Expand All @@ -24,6 +25,10 @@ const config = {
},
resolve: {
mainFields: ['module'],
alias: {
cockpit: path.resolve(__dirname, 'src/mocks/cockpit'),
fsinfo: path.resolve(__dirname, 'src/mocks/cockpit'),
},
},
esbuild: {
loader: 'tsx',
Expand Down

0 comments on commit 5cca844

Please sign in to comment.