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 5, 2024
1 parent 2760f5a commit b85d924
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 10 deletions.
65 changes: 55 additions & 10 deletions src/store/cockpitApi.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import TOML from '@ltd/j-toml';
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

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

// we could create an alias for this, something like
// import cockpit from 'cockpit', but this feels like
// a bit of magic and might make the code harder to
// maintain.
import cockpit from '../../pkg/lib/cockpit';
import { fsinfo } from '../../pkg/lib/cockpit/fsinfo';

const emptyCockpitApi = createApi({
reducerPath: 'cockpitApi',
baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
Expand All @@ -28,22 +37,58 @@ 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 {
if (!cockpit) {
throw new Error('Cockpit API is not available');
}

const user = await cockpit.user();

// we will use the user's `.local` directory
// to save blueprints used for on-prem
// TODO: remove the hardcode
const path = `${user.home}/.local/share/cockpit/image-builder-frontend/blueprints`;

// 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();

return {
name: parsed.name as string,
id: parsed.name as string, // TODO: duplicate name case
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: error.message };
}
},
}),
};
Expand Down
22 changes: 22 additions & 0 deletions src/test/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,28 @@ vi.mock('@unleash/proxy-client-react', () => ({
}),
}));

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

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

// Remove DOM dump from the testing-library output
configure({
getElementError: (message: string) => {
Expand Down

0 comments on commit b85d924

Please sign in to comment.