11import type { LogOutputChannel } from "vscode" ;
2+ import * as z from "zod/v4-mini" ;
23
34import { checkIsAuthenticated } from "./authenticate.ts" ;
45import { checkIsProfileConfigured } from "./configure-aws.ts" ;
6+ import { exec } from "./exec.ts" ;
57import { checkLocalstackInstalled } from "./install.ts" ;
68import { checkIsLicenseValid } from "./license.ts" ;
9+ import { spawn } from "./spawn.ts" ;
710
811export async function checkSetupStatus ( outputChannel : LogOutputChannel ) {
912 const [ isInstalled , isAuthenticated , isLicenseValid , isProfileConfigured ] =
@@ -21,3 +24,69 @@ export async function checkSetupStatus(outputChannel: LogOutputChannel) {
2124 isProfileConfigured,
2225 } ;
2326}
27+
28+ const LOCALSTACK_DOCKER_IMAGE = "localstack/localstack-pro" ;
29+
30+ export async function updateDockerImage (
31+ outputChannel : LogOutputChannel ,
32+ ) : Promise < void > {
33+ const imageVersion = await getDockerImageSemverVersion ( outputChannel ) ;
34+ if ( ! imageVersion ) {
35+ await pullDockerImage ( outputChannel ) ;
36+ }
37+ }
38+
39+ const InspectSchema = z . array (
40+ z . object ( {
41+ Config : z . object ( {
42+ Env : z . array ( z . string ( ) ) ,
43+ } ) ,
44+ } ) ,
45+ ) ;
46+
47+ async function inspectDockerImage (
48+ outputChannel : LogOutputChannel ,
49+ ) : Promise < string | undefined > {
50+ try {
51+ const { stdout } = await exec ( `docker inspect ${ LOCALSTACK_DOCKER_IMAGE } ` ) ;
52+ const data : unknown = JSON . parse ( stdout ) ;
53+ const parsed = InspectSchema . safeParse ( data ) ;
54+ if ( ! parsed . success ) {
55+ throw new Error (
56+ `Could not parse "docker inspect" output: ${ JSON . stringify ( z . treeifyError ( parsed . error ) ) } ` ,
57+ ) ;
58+ }
59+ const env = parsed . data [ 0 ] ?. Config . Env ?? [ ] ;
60+ const version = env
61+ . find ( ( line ) => line . startsWith ( "LOCALSTACK_BUILD_VERSION=" ) )
62+ ?. slice ( "LOCALSTACK_BUILD_VERSION=" . length ) ;
63+ return version ;
64+ } catch ( error ) {
65+ outputChannel . error ( "Could not inspect LocalStack docker image" ) ;
66+ outputChannel . error ( error instanceof Error ? error : String ( error ) ) ;
67+ return undefined ;
68+ }
69+ }
70+
71+ async function getDockerImageSemverVersion (
72+ outputChannel : LogOutputChannel ,
73+ ) : Promise < string | undefined > {
74+ const imageVersion = await inspectDockerImage ( outputChannel ) ;
75+ if ( ! imageVersion ) {
76+ return ;
77+ }
78+
79+ return imageVersion ;
80+ }
81+
82+ async function pullDockerImage ( outputChannel : LogOutputChannel ) : Promise < void > {
83+ try {
84+ await spawn ( "docker" , [ "pull" , LOCALSTACK_DOCKER_IMAGE ] , {
85+ outputChannel,
86+ outputLabel : "docker.pull" ,
87+ } ) ;
88+ } catch ( error ) {
89+ outputChannel . error ( "Could not pull LocalStack docker image" ) ;
90+ outputChannel . error ( error instanceof Error ? error : String ( error ) ) ;
91+ }
92+ }
0 commit comments