@@ -47,27 +47,32 @@ export class E2BSandboxRunner implements SandboxRunner {
4747 appendLog ?.( chunk ) ;
4848 } ;
4949
50- // Run terraform init
50+ // Run terraform init (with AWS creds if configured for benchmark)
51+ const metadata = job . payload . metadata ;
5152 await this . runTerraformCommand (
5253 sandbox ,
5354 workDir ,
5455 [ "init" , "-input=false" , "-no-color" ] ,
5556 logs ,
5657 streamLog ,
58+ metadata ,
5759 ) ;
5860
5961 // Run terraform plan
6062 const planArgs = [ "plan" , "-input=false" , "-no-color" , "-out=tfplan.binary" ] ;
6163 if ( job . payload . isDestroy ) {
6264 planArgs . splice ( 1 , 0 , "-destroy" ) ;
6365 }
64- await this . runTerraformCommand ( sandbox , workDir , planArgs , logs , streamLog ) ;
66+ await this . runTerraformCommand ( sandbox , workDir , planArgs , logs , streamLog , metadata ) ;
6567
6668 // Get plan JSON
6769 const showResult = await this . runTerraformCommand (
6870 sandbox ,
6971 workDir ,
7072 [ "show" , "-json" , "tfplan.binary" ] ,
73+ undefined ,
74+ undefined ,
75+ metadata ,
7176 ) ;
7277
7378 const planJSON = showResult . stdout ;
@@ -103,30 +108,61 @@ export class E2BSandboxRunner implements SandboxRunner {
103108 appendLog ?.( chunk ) ;
104109 } ;
105110
106- // Run terraform init
111+ // Run terraform init (with AWS creds if configured for benchmark)
112+ const metadata = job . payload . metadata ;
107113 await this . runTerraformCommand (
108114 sandbox ,
109115 workDir ,
110116 [ "init" , "-input=false" , "-no-color" ] ,
111117 logs ,
112118 streamLog ,
119+ metadata ,
113120 ) ;
114121
115122 // Run terraform apply/destroy
116123 const applyCommand = job . payload . isDestroy ? "destroy" : "apply" ;
117- await this . runTerraformCommand (
124+ const applyResult = await this . runTerraformCommand (
118125 sandbox ,
119126 workDir ,
120127 [ applyCommand , "-auto-approve" , "-input=false" , "-no-color" ] ,
121128 logs ,
122129 streamLog ,
130+ metadata ,
123131 ) ;
124132
125- // Read the state file
126- const statePath = `${ workDir } /terraform.tfstate` ;
127- const stateContent = await sandbox . files . read ( statePath ) ;
133+ // Log the apply output for debugging
134+ logger . info ( {
135+ stdout : applyResult . stdout . slice ( - 500 ) ,
136+ stderr : applyResult . stderr . slice ( - 500 ) ,
137+ } , "terraform apply output (last 500 chars)" ) ;
138+
139+ // Use terraform show to get state - works regardless of workspace configuration
140+ // This handles both: terraform.tfstate and terraform.tfstate.d/<workspace>/terraform.tfstate
141+ let stateBase64 = "" ;
142+
143+ try {
144+ const showResult = await this . runTerraformCommand (
145+ sandbox ,
146+ workDir ,
147+ [ "show" , "-json" ] ,
148+ undefined ,
149+ undefined ,
150+ metadata ,
151+ ) ;
152+
153+ if ( showResult . stdout && showResult . stdout . trim ( ) !== "{}" ) {
154+ stateBase64 = Buffer . from ( showResult . stdout , "utf8" ) . toString ( "base64" ) ;
155+ logger . info ( { stateSize : showResult . stdout . length } , "captured state via terraform show" ) ;
156+ } else {
157+ logger . info ( "terraform show returned empty state" ) ;
158+ }
159+ } catch ( err ) {
160+ // State doesn't exist - this is OK for empty applies or destroys
161+ logger . warn ( { error : err } , "no state found after apply (may be empty apply)" ) ;
162+ }
163+
128164 const result : SandboxRunResult = {
129- state : Buffer . from ( stateContent , "utf8" ) . toString ( "base64" ) ,
165+ state : stateBase64 ,
130166 } ;
131167
132168 return { logs : logs . join ( "" ) , result } ;
@@ -169,6 +205,27 @@ export class E2BSandboxRunner implements SandboxRunner {
169205 return { sandbox, needsInstall } ;
170206 }
171207
208+ /**
209+ * Build environment variables for Terraform execution.
210+ * Includes AWS credentials if provided in metadata for benchmark runs.
211+ */
212+ private buildTerraformEnvs ( metadata ?: Record < string , string > ) : Record < string , string > {
213+ const envs : Record < string , string > = {
214+ TF_IN_AUTOMATION : "1" ,
215+ } ;
216+
217+ // Inject AWS credentials if provided (for benchmark runs with real resources)
218+ if ( metadata ?. AWS_ACCESS_KEY_ID ) {
219+ envs . AWS_ACCESS_KEY_ID = metadata . AWS_ACCESS_KEY_ID ;
220+ envs . AWS_SECRET_ACCESS_KEY = metadata . AWS_SECRET_ACCESS_KEY || "" ;
221+ envs . AWS_REGION = metadata . AWS_REGION || "us-east-1" ;
222+ // Also set default region for AWS SDK
223+ envs . AWS_DEFAULT_REGION = envs . AWS_REGION ;
224+ }
225+
226+ return envs ;
227+ }
228+
172229
173230 private async installIacTool ( sandbox : Sandbox , engine : string , version : string ) : Promise < void > {
174231 logger . info ( { engine, version } , "installing IaC tool at runtime" ) ;
@@ -231,6 +288,20 @@ export class E2BSandboxRunner implements SandboxRunner {
231288 // Use gunzip + tar separately for better compatibility across tar versions
232289 await sandbox . commands . run ( `cd ${ workDir } && gunzip -c bundle.tar.gz | tar -x --exclude='terraform.tfstate' --exclude='terraform.tfstate.backup'` ) ;
233290
291+ // Debug: List extracted files to understand archive structure
292+ const listResult = await sandbox . commands . run ( `find ${ workDir } -type f -name "*.tf" | head -20` ) ;
293+ logger . info ( {
294+ tfFiles : listResult . stdout . trim ( ) . split ( '\n' ) . filter ( Boolean ) ,
295+ workDir,
296+ workingDirectory : job . payload . workingDirectory || '(none)'
297+ } , "extracted terraform files" ) ;
298+
299+ // Also list all files for debugging
300+ const allFilesResult = await sandbox . commands . run ( `ls -la ${ workDir } ` ) ;
301+ logger . info ( {
302+ files : allFilesResult . stdout
303+ } , "workspace directory listing" ) ;
304+
234305 // Determine the execution directory
235306 const execDir = job . payload . workingDirectory
236307 ? `${ workDir } /${ job . payload . workingDirectory } `
@@ -273,6 +344,7 @@ export class E2BSandboxRunner implements SandboxRunner {
273344 args : string [ ] ,
274345 logBuffer ?: string [ ] ,
275346 appendLog ?: ( chunk : string ) => void ,
347+ metadata ?: Record < string , string > ,
276348 ) : Promise < { stdout : string ; stderr : string } > {
277349 const engine = ( sandbox as any ) . _requestedEngine || "terraform" ;
278350 const binaryName = engine === "tofu" ? "tofu" : "terraform" ;
@@ -291,9 +363,7 @@ export class E2BSandboxRunner implements SandboxRunner {
291363
292364 const result = await sandbox . commands . run ( cmdStr , {
293365 cwd,
294- envs : {
295- TF_IN_AUTOMATION : "1" ,
296- } ,
366+ envs : this . buildTerraformEnvs ( metadata ) ,
297367 onStdout : pipeChunk ,
298368 onStderr : pipeChunk ,
299369 } ) ;
0 commit comments