-
Notifications
You must be signed in to change notification settings - Fork 4
feat: pre-fetch docker image #36
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
Changes from 7 commits
7a0384c
f5a2667
2653a5c
15bc2b7
ecca7d6
878347d
f111456
a8f425c
1836fa3
035ece4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |
| activateLicenseUntilValid, | ||
| } from "../utils/license.ts"; | ||
| import { minDelay } from "../utils/promises.ts"; | ||
| import { updateDockerImage } from "../utils/setup.ts"; | ||
|
|
||
| export default createPlugin( | ||
| "setup", | ||
|
|
@@ -60,7 +61,7 @@ | |
| }, | ||
| }); | ||
|
|
||
| window.withProgress( | ||
| { | ||
| location: ProgressLocation.Notification, | ||
| title: "Setup LocalStack", | ||
|
|
@@ -93,6 +94,14 @@ | |
| } | ||
| } | ||
|
|
||
| let imagePulled = false; | ||
| const pullImageProcess = updateDockerImage( | ||
| outputChannel, | ||
| cancellationToken, | ||
| ).then(() => { | ||
| imagePulled = true; | ||
| }); | ||
|
|
||
| ///////////////////////////////////////////////////////////////////// | ||
| progress.report({ | ||
| message: "Verifying authentication...", | ||
|
|
@@ -195,7 +204,7 @@ | |
| "License is not valid or not assigned. Open License settings page to activate it.", | ||
| }); | ||
|
|
||
| commands.executeCommand("localstack.openLicensePage"); | ||
| await commands.executeCommand("localstack.openLicensePage"); | ||
|
|
||
| await activateLicenseUntilValid( | ||
| outputChannel, | ||
|
|
@@ -220,34 +229,53 @@ | |
| }), | ||
| ); | ||
|
|
||
| commands.executeCommand("localstack.refreshStatusBar"); | ||
| await commands.executeCommand("localstack.refreshStatusBar"); | ||
|
|
||
| progress.report({ | ||
| message: 'Finished configuring "localstack" AWS profiles.', | ||
| }); | ||
| await minDelay(Promise.resolve()); | ||
|
|
||
| if (!imagePulled) { | ||
| progress.report({ | ||
| message: "Downloading LocalStack docker image...", | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit capitalization: @tiurin "Docker" as a name is preferably capitalized
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks, will fix it in one of the upcoming releases. |
||
| }); | ||
| await minDelay(pullImageProcess); | ||
| } | ||
|
|
||
| if (cancellationToken.isCancellationRequested) { | ||
| telemetry.track({ | ||
| name: "setup_ended", | ||
| payload: { | ||
| namespace: "onboarding", | ||
| steps: [1, 2, 3], | ||
| status: "CANCELLED", | ||
| }, | ||
| }); | ||
| return; | ||
| } | ||
|
|
||
| ///////////////////////////////////////////////////////////////////// | ||
| if (localStackStatusTracker.status() === "running") { | ||
| window | ||
|
skyrpex marked this conversation as resolved.
|
||
| .showInformationMessage("LocalStack is running.", { | ||
| title: "View Logs", | ||
| command: "localstack.viewLogs", | ||
| }) | ||
| .then((selection) => { | ||
| if (selection) { | ||
| commands.executeCommand(selection.command); | ||
| } | ||
| }); | ||
| } else { | ||
| window | ||
| .showInformationMessage("LocalStack is ready to start.", { | ||
| title: "Start LocalStack", | ||
| command: "localstack.start", | ||
| }) | ||
| .then((selection) => { | ||
| if (selection) { | ||
| commands.executeCommand(selection.command); | ||
| } | ||
| }); | ||
| } | ||
|
|
@@ -267,14 +295,14 @@ | |
| ); | ||
|
|
||
| if (setupStatusTracker.status() === "setup_required") { | ||
| window | ||
| .showInformationMessage("Setup LocalStack to get started.", { | ||
| title: "Setup", | ||
| command: "localstack.setup", | ||
| }) | ||
| .then((selected) => { | ||
| if (selected) { | ||
| commands.executeCommand(selected.command, "extension_startup"); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,12 @@ | ||
| import type { LogOutputChannel } from "vscode"; | ||
| import type { CancellationToken, LogOutputChannel } from "vscode"; | ||
| import * as z from "zod/v4-mini"; | ||
|
|
||
| import { checkIsAuthenticated } from "./authenticate.ts"; | ||
| import { checkIsProfileConfigured } from "./configure-aws.ts"; | ||
| import { exec } from "./exec.ts"; | ||
| import { checkLocalstackInstalled } from "./install.ts"; | ||
| import { checkIsLicenseValid } from "./license.ts"; | ||
| import { spawn } from "./spawn.ts"; | ||
|
|
||
| export async function checkSetupStatus(outputChannel: LogOutputChannel) { | ||
| const [isInstalled, isAuthenticated, isLicenseValid, isProfileConfigured] = | ||
|
|
@@ -21,3 +24,66 @@ export async function checkSetupStatus(outputChannel: LogOutputChannel) { | |
| isProfileConfigured, | ||
| }; | ||
| } | ||
|
|
||
| const LOCALSTACK_DOCKER_IMAGE = "localstack/localstack-pro"; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can import this constant from
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great point, let's make sure we download what we are going to use! 😄 Moved to global constants module. |
||
|
|
||
| export async function updateDockerImage( | ||
| outputChannel: LogOutputChannel, | ||
| cancellationToken: CancellationToken, | ||
| ): Promise<void> { | ||
| const imageVersion = await getDockerImageSemverVersion(outputChannel); | ||
| if (!imageVersion) { | ||
| await pullDockerImage(outputChannel, cancellationToken); | ||
| } | ||
| } | ||
|
|
||
| const InspectSchema = z.array( | ||
| z.object({ | ||
| Config: z.object({ | ||
| Env: z.array(z.string()), | ||
| }), | ||
| }), | ||
| ); | ||
|
|
||
| async function getDockerImageSemverVersion( | ||
| outputChannel: LogOutputChannel, | ||
| ): Promise<string | undefined> { | ||
| try { | ||
| const { stdout } = await exec(`docker inspect ${LOCALSTACK_DOCKER_IMAGE}`); | ||
| const data: unknown = JSON.parse(stdout); | ||
| const parsed = InspectSchema.safeParse(data); | ||
| if (!parsed.success) { | ||
| throw new Error( | ||
| `Could not parse "docker inspect" output: ${JSON.stringify(z.treeifyError(parsed.error))}`, | ||
| ); | ||
| } | ||
| const env = parsed.data[0]?.Config.Env ?? []; | ||
| const imageVersion = env | ||
| .find((line) => line.startsWith("LOCALSTACK_BUILD_VERSION=")) | ||
| ?.slice("LOCALSTACK_BUILD_VERSION=".length); | ||
| if (!imageVersion) { | ||
| return; | ||
| } | ||
| return imageVersion; | ||
| } catch (error) { | ||
| outputChannel.error("Could not inspect LocalStack docker image"); | ||
| outputChannel.error(error instanceof Error ? error : String(error)); | ||
| return undefined; | ||
| } | ||
| } | ||
|
|
||
| async function pullDockerImage( | ||
| outputChannel: LogOutputChannel, | ||
| cancellationToken: CancellationToken, | ||
| ): Promise<void> { | ||
| try { | ||
| await spawn("docker", ["pull", LOCALSTACK_DOCKER_IMAGE], { | ||
| outputChannel, | ||
| outputLabel: "docker.pull", | ||
| cancellationToken: cancellationToken, | ||
| }); | ||
| } catch (error) { | ||
| outputChannel.error("Could not pull LocalStack docker image"); | ||
| outputChannel.error(error instanceof Error ? error : String(error)); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.