Skip to content

Commit 357038a

Browse files
authored
feat: add chown (linux only) (#695)
* feat: add chown (linux only) ### What does this PR do? * Adds chown to the advanced settings page for build * Only applicable to Linux (see: osbuild/bootc-image-builder#576) ### Screenshot / video of UI <!-- If this PR is changing UI, please include screenshots or screencasts showing the difference --> ### What issues does this PR fix or reference? <!-- Include any related issues from Podman Desktop repository (or from another issue tracker). --> Closes #472 ### How to test this PR? <!-- Please explain steps to reproduce --> 1. Be on Linux 2. Build an image 3. See that it is chown (ex. ls -l /outputdir) Signed-off-by: Charlie Drage <[email protected]> * by default fill in uid and gid Signed-off-by: Charlie Drage <[email protected]> --------- Signed-off-by: Charlie Drage <[email protected]>
1 parent 7df2443 commit 357038a

File tree

8 files changed

+86
-1
lines changed

8 files changed

+86
-1
lines changed

packages/backend/src/api-impl.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { History } from './history';
2525
import * as containerUtils from './container-utils';
2626
import { Messages } from '/@shared/src/messages/Messages';
2727
import { telemetryLogger } from './extension';
28-
import { checkPrereqs, isLinux } from './machine-utils';
28+
import { checkPrereqs, isLinux, getUidGid } from './machine-utils';
2929

3030
export class BootcApiImpl implements BootcApi {
3131
private history: History;
@@ -244,6 +244,10 @@ export class BootcApiImpl implements BootcApi {
244244
return isLinux();
245245
}
246246

247+
async getUidGid(): Promise<string> {
248+
return getUidGid();
249+
}
250+
247251
// The API does not allow callbacks through the RPC, so instead
248252
// we send "notify" messages to the frontend to trigger a refresh
249253
// this method is internal and meant to be used by the API implementation

packages/backend/src/build-disk-image.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,3 +431,28 @@ test('test build config json passed in', async () => {
431431
expect(options.HostConfig.Binds[2]).toEqual(build.buildConfigFilePath + ':/config.json:ro');
432432
}
433433
});
434+
435+
test('test chown works when passed into createBuilderImageOptions', async () => {
436+
const name = 'test123-bootc-image-builder';
437+
const build = {
438+
image: 'test-image',
439+
tag: 'latest',
440+
type: ['raw'],
441+
arch: 'amd64',
442+
folder: '/tmp/foo/bar/qemutest4',
443+
chown: '1000:1000',
444+
} as BootcBuildInfo;
445+
446+
const options = createBuilderImageOptions(name, build);
447+
448+
expect(options).toBeDefined();
449+
expect(options.HostConfig).toBeDefined();
450+
expect(options.HostConfig?.Binds).toBeDefined();
451+
if (options.HostConfig?.Binds) {
452+
expect(options.HostConfig.Binds.length).toEqual(2);
453+
expect(options.HostConfig.Binds[0]).toEqual(build.folder + ':/output/');
454+
expect(options.HostConfig.Binds[1]).toEqual('/var/lib/containers/storage:/var/lib/containers/storage');
455+
}
456+
expect(options.Cmd).toContain('--chown');
457+
expect(options.Cmd).toContain(build.chown);
458+
});

packages/backend/src/build-disk-image.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,11 @@ export function createBuilderImageOptions(
455455
}
456456
}
457457

458+
// If there is the chown in build, add the --chown flag to the command with the value in chown
459+
if (build.chown) {
460+
cmd.push('--chown', build.chown);
461+
}
462+
458463
return options;
459464
}
460465

packages/backend/src/machine-utils.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,12 @@ const linux = os.platform() === 'linux';
138138
export function isLinux(): boolean {
139139
return linux;
140140
}
141+
142+
// Get the GID and UID of the current user and return in the format gid:uid
143+
// in order for this to work, we must get this information from process.exec
144+
// since there is no native way via node
145+
export async function getUidGid(): Promise<string> {
146+
const { stdout: uidOutput } = await extensionApi.process.exec('id', ['-u']);
147+
const { stdout: gidOutput } = await extensionApi.process.exec('id', ['-g']);
148+
return `${uidOutput.trim()}:${gidOutput.trim()}`;
149+
}

packages/frontend/src/Build.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,4 +728,7 @@ test('collapse and uncollapse of advanced options', async () => {
728728
// expect build config to be shown
729729
const buildConfig2 = screen.queryByRole('label', { name: 'Build config' });
730730
expect(buildConfig2).toBeDefined();
731+
// Expect chown to be shown
732+
const chown = screen.queryByRole('label', { name: 'Change file owner and group' });
733+
expect(chown).toBeDefined();
731734
});

packages/frontend/src/Build.svelte

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ let availableArchitectures: string[] = [];
3434
// Build options
3535
let buildFolder: string;
3636
let buildConfigFile: string;
37+
let buildChown: string;
3738
let buildType: BuildType[] = [];
3839
let buildArch: string | undefined;
3940
let buildFilesystem: string = ''; // Default filesystem auto-selected / empty
@@ -124,6 +125,17 @@ async function fillArchitectures(historyInfo: BootcBuildInfo[]) {
124125
}
125126
}
126127
128+
// This will fill the chown function by getting the user and group ID from the OS
129+
// and filling in the information in the chown input field.
130+
async function fillChownOption() {
131+
try {
132+
const gidUid = await bootcClient.getUidGid();
133+
buildChown = gidUid;
134+
} catch (error) {
135+
console.error('Error getting UID and GID:', error);
136+
}
137+
}
138+
127139
async function validate() {
128140
let prereqs = await bootcClient.checkPrereqs();
129141
if (prereqs) {
@@ -193,6 +205,7 @@ async function buildBootcImage() {
193205
type: buildType,
194206
arch: buildArch,
195207
filesystem: buildFilesystem,
208+
chown: buildChown,
196209
awsAmiName: awsAmiName,
197210
awsBucket: awsBucket,
198211
awsRegion: awsRegion,
@@ -291,6 +304,10 @@ onMount(async () => {
291304
await fillBuildOptions(historyInfo);
292305
await fillArchitectures(historyInfo);
293306
307+
if (isLinux) {
308+
await fillChownOption();
309+
}
310+
294311
validate();
295312
});
296313
@@ -689,6 +706,26 @@ export function goToHomePage(): void {
689706
</p>
690707
</div>
691708

709+
<!-- chown, this option is only available for Linux users -->
710+
{#if isLinux}
711+
<div class="mb-2">
712+
<label for="chown" class="block mb-2 font-semibold">Change file owner and group</label>
713+
<div class="flex flex-row space-x-3">
714+
<Input
715+
name="chown"
716+
id="chown"
717+
bind:value={buildChown}
718+
placeholder="UID and GID parameters (ex. 1000:1000)"
719+
class="w-full"
720+
aria-label="chown-select" />
721+
</div>
722+
<p class="text-sm text-[var(--pd-content-text)] pt-2">
723+
Linux only. By default the UID and GID of the current user is used. This option allows you to
724+
change the owner and group of the files in the output directory.
725+
</p>
726+
</div>
727+
{/if}
728+
692729
<!-- AWS -->
693730
<div>
694731
<span class="font-semibold block">Upload image to AWS</span>

packages/shared/src/BootcAPI.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export abstract class BootcApi {
3636
abstract generateUniqueBuildID(name: string): Promise<string>;
3737
abstract openLink(link: string): Promise<void>;
3838
abstract isLinux(): Promise<boolean>;
39+
abstract getUidGid(): Promise<string>;
3940
abstract telemetryLogUsage(eventName: string, data?: Record<string, unknown> | undefined): Promise<void>;
4041
abstract telemetryLogError(eventName: string, data?: Record<string, unknown> | undefined): Promise<void>;
4142
}

packages/shared/src/models/bootc.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export interface BootcBuildInfo {
2626
engineId: string;
2727
type: BuildType[];
2828
folder: string;
29+
chown?: string;
2930
buildConfigFilePath?: string;
3031
filesystem?: string;
3132
arch?: string;

0 commit comments

Comments
 (0)