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

feat: support rhel bib #449

Merged
merged 4 commits into from
May 6, 2024
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
9 changes: 9 additions & 0 deletions packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@
"default": 30,
"maximum": 120,
"description": "Build timeout (in minutes)"
},
"bootc.builder": {
"type": "string",
"default": "CentOS",
"enum": [
"CentOS",
"RHEL"
],
"description": "Builder image used to create disk images"
}
}
},
Expand Down
51 changes: 46 additions & 5 deletions packages/backend/src/build-disk-image.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,22 @@
***********************************************************************/

import { beforeEach, expect, test, vi } from 'vitest';
import { buildExists, createBuilderImageOptions, getUnusedName } from './build-disk-image';
import { bootcImageBuilderName } from './constants';
import type { ContainerInfo } from '@podman-desktop/api';
import { buildExists, createBuilderImageOptions, getBuilder, getUnusedName } from './build-disk-image';
import { bootcImageBuilderCentos, bootcImageBuilderRHEL } from './constants';
import type { ContainerInfo, Configuration } from '@podman-desktop/api';
import { containerEngine } from '@podman-desktop/api';
import type { BootcBuildInfo } from '/@shared/src/models/bootc';
import * as fs from 'node:fs';
import { resolve } from 'node:path';

const configurationGetConfigurationMock = vi.fn();

const config: Configuration = {
get: configurationGetConfigurationMock,
has: () => true,
update: vi.fn(),
};

vi.mock('@podman-desktop/api', async () => {
return {
env: {
Expand All @@ -33,6 +41,9 @@ vi.mock('@podman-desktop/api', async () => {
containerEngine: {
listContainers: vi.fn().mockReturnValue([]),
},
configuration: {
getConfiguration: () => config,
},
};
});

Expand All @@ -53,7 +64,7 @@ test('check image builder options', async () => {

expect(options).toBeDefined();
expect(options.name).toEqual(name);
expect(options.Image).toEqual(bootcImageBuilderName);
expect(options.Image).toEqual(bootcImageBuilderCentos);
expect(options.HostConfig).toBeDefined();
if (options.HostConfig?.Binds) {
expect(options.HostConfig.Binds[0]).toEqual(build.folder + ':/output/');
Expand Down Expand Up @@ -84,7 +95,7 @@ test('check image builder with multiple types', async () => {

expect(options).toBeDefined();
expect(options.name).toEqual(name);
expect(options.Image).toEqual(bootcImageBuilderName);
expect(options.Image).toEqual(bootcImageBuilderCentos);
expect(options.HostConfig).toBeDefined();
if (options.HostConfig?.Binds) {
expect(options.HostConfig.Binds[0]).toEqual(build.folder + ':/output/');
Expand Down Expand Up @@ -181,6 +192,18 @@ test('test if blank string is passed into filesystem, it is not included in the
expect(options.Cmd).not.toContain('--rootfs');
});

test('test specified builder is used', async () => {
const builder = 'foo-builder';
const build = {
image: 'test-image',
type: ['vmdk'],
} as BootcBuildInfo;
const options = createBuilderImageOptions('my-image', build, builder);

expect(options).toBeDefined();
expect(options.Image).toEqual(builder);
});

test('check we pick unused container name', async () => {
const basename = 'test';
let name = await getUnusedName(basename);
Expand Down Expand Up @@ -230,3 +253,21 @@ test('check build exists', async () => {
exists = await buildExists(folder, ['iso', 'raw']);
expect(exists).toEqual(false);
});

test('check uses RHEL builder', async () => {
configurationGetConfigurationMock.mockReturnValue('RHEL');

const builder = await getBuilder();

expect(builder).toBeDefined();
expect(builder).toEqual(bootcImageBuilderRHEL);
});

test('check uses Centos builder', async () => {
configurationGetConfigurationMock.mockReturnValue('CentOS');

const builder = await getBuilder();

expect(builder).toBeDefined();
expect(builder).toEqual(bootcImageBuilderCentos);
});
31 changes: 25 additions & 6 deletions packages/backend/src/build-disk-image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ import * as extensionApi from '@podman-desktop/api';
import * as fs from 'node:fs';
import { resolve } from 'node:path';
import * as containerUtils from './container-utils';
import { bootcImageBuilderContainerName, bootcImageBuilderName } from './constants';
import { bootcImageBuilder, bootcImageBuilderCentos, bootcImageBuilderRHEL } from './constants';
import type { BootcBuildInfo, BuildType } from '/@shared/src/models/bootc';
import type { History } from './history';
import * as machineUtils from './machine-utils';
import { telemetryLogger } from './extension';
import { getConfigurationValue, telemetryLogger } from './extension';

export async function buildExists(folder: string, types: BuildType[]) {
let exists = false;
Expand Down Expand Up @@ -100,7 +100,7 @@ export async function buildDiskImage(build: BootcBuildInfo, history: History, ov
.withProgress(
{ location: extensionApi.ProgressLocation.TASK_WIDGET, title: `Building disk image ${build.image}` },
async progress => {
const buildContainerName = build.image.split('/').pop() + bootcImageBuilderContainerName;
const buildContainerName = build.image.split('/').pop() + '-' + bootcImageBuilder;
let successful: boolean = false;
let logData: string = 'Build Image Log --------\n';
logData += 'ID: ' + build.id + '\n';
Expand All @@ -118,11 +118,14 @@ export async function buildDiskImage(build: BootcBuildInfo, history: History, ov
fs.unlinkSync(logPath);
}

// determine which bootc image builder to use
const builder = await getBuilder();

// Preliminary Step 0. Create the "bootc-image-builder" container
// options that we will use to build the image. This will help with debugging
// as well as making sure we delete the previous build, etc.
const containerName = await getUnusedName(buildContainerName);
const buildImageContainer = createBuilderImageOptions(containerName, build);
const buildImageContainer = createBuilderImageOptions(containerName, build, builder);
logData += JSON.stringify(buildImageContainer, undefined, 2);
logData += '\n----------\n';
try {
Expand Down Expand Up @@ -304,8 +307,24 @@ export async function getUnusedName(name: string): Promise<string> {
return unusedName;
}

export async function getBuilder(): Promise<string> {
// use the preference to decide which builder to use
const buildProp = await getConfigurationValue<string>('builder');

if (buildProp === 'RHEL') {
return bootcImageBuilderRHEL;
}

// always default to centos bib
return bootcImageBuilderCentos;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we fail at all if the config setting is not centos or rhel? i see in our tests it still passed.

example you can pass in anything 'foobar' as the configuration setting and it'll always pick centos.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to play it safe, i.e. even if config corrupted => we ignore and use CentOS anyway.

}

// Create builder options for the "bootc-image-builder" container
export function createBuilderImageOptions(name: string, build: BootcBuildInfo): ContainerCreateOptions {
export function createBuilderImageOptions(
name: string,
build: BootcBuildInfo,
builder?: string,
): ContainerCreateOptions {
const cmd = [`${build.image}:${build.tag}`, '--output', '/output/', '--local'];

build.type.forEach(t => cmd.push('--type', t));
Expand All @@ -323,7 +342,7 @@ export function createBuilderImageOptions(name: string, build: BootcBuildInfo):
// Create the image options for the "bootc-image-builder" container
const options: ContainerCreateOptions = {
name: name,
Image: bootcImageBuilderName,
Image: builder ?? bootcImageBuilderCentos,
Tty: true,
HostConfig: {
Privileged: true,
Expand Down
5 changes: 3 additions & 2 deletions packages/backend/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
***********************************************************************/

// Image related
export const bootcImageBuilderContainerName = '-bootc-image-builder';
export const bootcImageBuilderName = 'quay.io/centos-bootc/bootc-image-builder:latest-1714633180';
export const bootcImageBuilder = 'bootc-image-builder';
export const bootcImageBuilderCentos = 'quay.io/centos-bootc/bootc-image-builder:latest-1714633180';
export const bootcImageBuilderRHEL = 'registry.redhat.io/rhel9/bootc-image-builder:9.4';