Skip to content

Commit

Permalink
feat: add AWS uploading image
Browse files Browse the repository at this point in the history
### What does this PR do?

* Adds the ability to upload to AWS through build
* Toggled advanced features section

### 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 #487

### How to test this PR?

<!-- Please explain steps to reproduce -->

1. Add your credentials to ~/.aws/credentials
2. Build your image + provide your bucket, aminame, etc.

Signed-off-by: Charlie Drage <[email protected]>
  • Loading branch information
cdrage committed Jun 25, 2024
1 parent 2525c27 commit 9cd84df
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 2 deletions.
25 changes: 24 additions & 1 deletion packages/backend/src/build-disk-image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
import type { ContainerCreateOptions } from '@podman-desktop/api';
import * as extensionApi from '@podman-desktop/api';
import * as fs from 'node:fs';
import { resolve } from 'node:path';
import path, { resolve } from 'node:path';
import os from 'node:os';
import * as containerUtils from './container-utils';
import { bootcImageBuilder, bootcImageBuilderCentos, bootcImageBuilderRHEL } from './constants';
import type { BootcBuildInfo, BuildType } from '/@shared/src/models/bootc';
Expand Down Expand Up @@ -75,6 +76,17 @@ export async function buildDiskImage(build: BootcBuildInfo, history: History, ov
}
}

// If one of awsAmiName, awsBucket, or awsRegion is defined, all three must be defined
if (
(build.awsAmiName && !build.awsBucket) ??
(!build.awsAmiName && build.awsBucket) ??
(!build.awsAmiName && build.awsBucket && build.awsRegion)
) {
const response = 'If you are using AWS, you must provide an AMI name, bucket, and region.';
await extensionApi.window.showErrorMessage(response);
throw new Error(response);
}

// Use build.type to check for existing files
if (
!overwrite &&
Expand Down Expand Up @@ -359,6 +371,17 @@ export function createBuilderImageOptions(
Cmd: cmd,
};

// If awsAmiName, awsBucket, and awsRegion are defined. We will add the mounted volume
// of the OS homedir & the .aws directory to the container.
if (build.awsAmiName && build.awsBucket && build.awsRegion) {
// Add the commands to the container, --aws-ami-name, --aws-bucket, --aws-region
cmd.push('--aws-ami-name', build.awsAmiName, '--aws-bucket', build.awsBucket, '--aws-region', build.awsRegion);

if (options.HostConfig?.Binds) {
options?.HostConfig?.Binds.push(path.join(os.homedir(), '.aws') + ':/root/.aws:ro');
}
}

return options;
}

Expand Down
68 changes: 67 additions & 1 deletion packages/frontend/src/Build.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
<script lang="ts">
import './app.css';
import { faCheck, faCube, faQuestionCircle, faTriangleExclamation } from '@fortawesome/free-solid-svg-icons';
import {
faCaretDown,
faCaretRight,
faCheck,
faCube,
faQuestionCircle,
faTriangleExclamation,
} from '@fortawesome/free-solid-svg-icons';
import { bootcClient } from './api/client';
import type { BootcBuildInfo, BuildType } from '/@shared/src/models/bootc';
import Fa from 'svelte-fa';
Expand All @@ -9,6 +16,7 @@ import type { ImageInfo, ManifestInspectInfo } from '@podman-desktop/api';
import { router } from 'tinro';
import DiskImageIcon from './lib/DiskImageIcon.svelte';
import { Button, Input, EmptyScreen, FormPage } from '@podman-desktop/ui-svelte';
import Link from './lib/Link.svelte';
export let imageName: string | undefined = undefined;
export let imageTag: string | undefined = undefined;
Expand Down Expand Up @@ -44,6 +52,17 @@ let errorFormValidation: string | undefined = undefined;
// this boolean will be set to true if the selected image is Fedora and shown as a warning to the user.
let fedoraDetected = false;
// AWS Related
let awsAmiName: string = '';
let awsBucket: string = '';
let awsRegion: string = '';
// Show/hide advanced options
let showAdvanced = false; // State to show/hide advanced options
function toggleAdvanced() {
showAdvanced = !showAdvanced;
}
function findImage(repoTag: string): ImageInfo | undefined {
return bootcAvailableImages.find(
image => image.RepoTags && image.RepoTags.length > 0 && image.RepoTags[0] === repoTag,
Expand Down Expand Up @@ -170,6 +189,9 @@ async function buildBootcImage() {
type: buildType,
arch: buildArch,
filesystem: buildFilesystem,
awsAmiName: awsAmiName,
awsBucket: awsBucket,
awsRegion: awsRegion,
};
buildInProgress = true;
Expand Down Expand Up @@ -648,6 +670,50 @@ export function goToHomePage(): void {
within the image or manifest.
</p>
</div>
<div class="mb-2">
<!-- Use a span for this until we have a "dropdown toggle" UI element implemented. -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<span class="text-md font-semibold mb-2 block cursor-pointer" on:click="{toggleAdvanced}"
><Fa icon="{showAdvanced ? faCaretDown : faCaretRight}" class="inline-block mr-1" /> Advanced Options
</span>
{#if showAdvanced}
<div>
<span class="text-sm font-semibold mb-2 block">Upload image to AWS</span>
</div>

<label for="amiName" class="block mb-2 text-sm font-bold text-gray-400">AMI Name</label>
<Input
bind:value="{awsAmiName}"
name="amiName"
id="amiName"
placeholder="AMI Name to be used"
class="w-full" />

<label for="awsBucket" class="block mb-2 text-sm font-bold text-gray-400">S3 Bucket</label>
<Input
bind:value="{awsBucket}"
name="awsBucket"
id="awsBucket"
placeholder="AWS S3 bucket"
class="w-full" />

<label for="awsRegion" class="block mb-2 text-sm font-bold text-gray-400">S3 Region</label>
<Input
bind:value="{awsRegion}"
name="awsRegion"
id="awsRegion"
placeholder="AWS S3 region"
class="w-full" />

<p class="text-gray-300 text-xs pt-2">
This will upload the image to a specific AWS S3 bucket. Credentials stored at ~/.aws/credentials will
be used for uploading. You must have <Link
externalRef="https://docs.aws.amazon.com/vm-import/latest/userguide/required-permissions.html"
>vmimport service role</Link> configured to upload to the bucket.
</p>
{/if}
</div>
</div>
</div>
{#if existingBuild}
Expand Down
3 changes: 3 additions & 0 deletions packages/shared/src/models/bootc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ export interface BootcBuildInfo {
status?: BootcBuildStatus;
timestamp?: string;
buildContainerId?: string; // The image ID that is used to build the image
awsAmiName?: string;
awsBucket?: string;
awsRegion?: string;
}

export type BootcBuildStatus = 'running' | 'creating' | 'success' | 'error' | 'lost' | 'deleting';

0 comments on commit 9cd84df

Please sign in to comment.