11package main
22
33import (
4- "bytes"
54 "context"
65 "encoding/json"
76 "fmt"
8- "io"
97 "log"
108 "os"
119 "path/filepath"
12- "strings"
1310
14- "github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/build "
11+ "github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/deploy "
1512 "github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis"
16- "github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis/api/engine"
17- "github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis/sources/spec"
18- "github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/tmpl"
19- "github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/util"
2013 "github.com/urfave/cli/v2"
2114)
2215
23- const FILESERVER_PACKAGE = "fileserver"
24-
25- func fileserverURL (path ... string ) string {
26- return fmt .Sprintf ("http://%s/%s" , FILESERVER_PACKAGE , strings .Join (path , "/" ))
27- }
28-
2916type config struct {
3017 templateFile string
3118 dataFile string
@@ -57,298 +44,6 @@ func newConfig(c *cli.Context) (*config, error) {
5744 return cfg , nil
5845}
5946
60- type engineManager interface {
61- EnsureRunning () error
62- }
63-
64- type Main struct {
65- cfg * config
66- newDeployer func (opts ... kurtosis.KurtosisDeployerOptions ) (deployer , error )
67- engineManager engineManager
68- }
69-
70- func (m * Main ) localDockerImageOption () tmpl.TemplateContextOptions {
71- dockerBuilder := build .NewDockerBuilder (
72- build .WithDockerBaseDir (m .cfg .baseDir ),
73- build .WithDockerDryRun (m .cfg .dryRun ),
74- )
75-
76- imageTag := func (projectName string ) string {
77- return fmt .Sprintf ("%s:%s" , projectName , m .cfg .enclave )
78- }
79-
80- return tmpl .WithFunction ("localDockerImage" , func (projectName string ) (string , error ) {
81- return dockerBuilder .Build (projectName , imageTag (projectName ))
82- })
83- }
84-
85- func (m * Main ) localContractArtifactsOption (dir string ) tmpl.TemplateContextOptions {
86- contractsBundle := fmt .Sprintf ("contracts-bundle-%s.tar.gz" , m .cfg .enclave )
87- contractsBundlePath := func (_ string ) string {
88- return filepath .Join (dir , contractsBundle )
89- }
90- contractsURL := fileserverURL (contractsBundle )
91-
92- contractBuilder := build .NewContractBuilder (
93- build .WithContractBaseDir (m .cfg .baseDir ),
94- build .WithContractDryRun (m .cfg .dryRun ),
95- )
96-
97- return tmpl .WithFunction ("localContractArtifacts" , func (layer string ) (string , error ) {
98- bundlePath := contractsBundlePath (layer )
99- if err := contractBuilder .Build (layer , bundlePath ); err != nil {
100- return "" , err
101- }
102-
103- log .Printf ("%s: contract artifacts available at: %s\n " , layer , contractsURL )
104- return contractsURL , nil
105- })
106- }
107-
108- type PrestateInfo struct {
109- URL string `json:"url"`
110- Hashes map [string ]string `json:"hashes"`
111- }
112-
113- type localPrestateHolder struct {
114- info * PrestateInfo
115- baseDir string
116- buildDir string
117- dryRun bool
118- builder * build.PrestateBuilder
119- }
120-
121- func newLocalPrestateHolder (baseDir string , buildDir string , dryRun bool ) * localPrestateHolder {
122- return & localPrestateHolder {
123- baseDir : baseDir ,
124- buildDir : buildDir ,
125- dryRun : dryRun ,
126- builder : build .NewPrestateBuilder (
127- build .WithPrestateBaseDir (baseDir ),
128- build .WithPrestateDryRun (dryRun ),
129- ),
130- }
131- }
132-
133- func (h * localPrestateHolder ) GetPrestateInfo () (* PrestateInfo , error ) {
134- if h .info != nil {
135- return h .info , nil
136- }
137-
138- prestatePath := []string {"proofs" , "op-program" , "cannon" }
139- prestateURL := fileserverURL (prestatePath ... )
140-
141- // Create build directory with the final path structure
142- buildDir := filepath .Join (append ([]string {h .buildDir }, prestatePath ... )... )
143- if err := os .MkdirAll (buildDir , 0755 ); err != nil {
144- return nil , fmt .Errorf ("failed to create prestate build directory: %w" , err )
145- }
146-
147- info := & PrestateInfo {
148- URL : prestateURL ,
149- Hashes : make (map [string ]string ),
150- }
151-
152- if h .dryRun {
153- h .info = info
154- return info , nil
155- }
156-
157- // Map of known file prefixes to their keys
158- fileToKey := map [string ]string {
159- "prestate-proof.json" : "prestate" ,
160- "prestate-proof-mt64.json" : "prestate_mt64" ,
161- "prestate-proof-mt.json" : "prestate_mt" ,
162- "prestate-proof-interop.json" : "prestate_interop" ,
163- }
164-
165- // Build all prestate files directly in the target directory
166- if err := h .builder .Build (buildDir ); err != nil {
167- return nil , fmt .Errorf ("failed to build prestates: %w" , err )
168- }
169-
170- // Find and process all prestate files
171- matches , err := filepath .Glob (filepath .Join (buildDir , "prestate-proof*.json" ))
172- if err != nil {
173- return nil , fmt .Errorf ("failed to find prestate files: %w" , err )
174- }
175-
176- // Process each file to rename it to its hash
177- for _ , filePath := range matches {
178- content , err := os .ReadFile (filePath )
179- if err != nil {
180- return nil , fmt .Errorf ("failed to read prestate %s: %w" , filepath .Base (filePath ), err )
181- }
182-
183- var data struct {
184- Pre string `json:"pre"`
185- }
186- if err := json .Unmarshal (content , & data ); err != nil {
187- return nil , fmt .Errorf ("failed to parse prestate %s: %w" , filepath .Base (filePath ), err )
188- }
189-
190- // Store hash with its corresponding key
191- if key , exists := fileToKey [filepath .Base (filePath )]; exists {
192- info .Hashes [key ] = data .Pre
193- }
194-
195- // Rename files to hash-based names
196- newFileName := data .Pre + ".json"
197- hashedPath := filepath .Join (buildDir , newFileName )
198- if err := os .Rename (filePath , hashedPath ); err != nil {
199- return nil , fmt .Errorf ("failed to rename prestate %s: %w" , filepath .Base (filePath ), err )
200- }
201- log .Printf ("%s available at: %s/%s\n " , filepath .Base (filePath ), prestateURL , newFileName )
202-
203- // Rename the corresponding binary file
204- binFilePath := strings .Replace (strings .TrimSuffix (filePath , ".json" ), "-proof" , "" , 1 ) + ".bin.gz"
205- newBinFileName := data .Pre + ".bin.gz"
206- binHashedPath := filepath .Join (buildDir , newBinFileName )
207- if err := os .Rename (binFilePath , binHashedPath ); err != nil {
208- return nil , fmt .Errorf ("failed to rename prestate %s: %w" , filepath .Base (binFilePath ), err )
209- }
210- log .Printf ("%s available at: %s/%s\n " , filepath .Base (binFilePath ), prestateURL , newBinFileName )
211- }
212-
213- h .info = info
214- return info , nil
215- }
216-
217- func (m * Main ) localPrestateOption (dir string ) tmpl.TemplateContextOptions {
218- holder := newLocalPrestateHolder (m .cfg .baseDir , dir , m .cfg .dryRun )
219-
220- return tmpl .WithFunction ("localPrestate" , func () (* PrestateInfo , error ) {
221- return holder .GetPrestateInfo ()
222- })
223- }
224-
225- func (m * Main ) renderTemplate (dir string ) (* bytes.Buffer , error ) {
226- opts := []tmpl.TemplateContextOptions {
227- m .localDockerImageOption (),
228- m .localContractArtifactsOption (dir ),
229- m .localPrestateOption (dir ),
230- tmpl .WithBaseDir (m .cfg .baseDir ),
231- }
232-
233- // Read and parse the data file if provided
234- if m .cfg .dataFile != "" {
235- data , err := os .ReadFile (m .cfg .dataFile )
236- if err != nil {
237- return nil , fmt .Errorf ("error reading data file: %w" , err )
238- }
239-
240- var templateData map [string ]interface {}
241- if err := json .Unmarshal (data , & templateData ); err != nil {
242- return nil , fmt .Errorf ("error parsing JSON data: %w" , err )
243- }
244-
245- opts = append (opts , tmpl .WithData (templateData ))
246- }
247-
248- // Open template file
249- tmplFile , err := os .Open (m .cfg .templateFile )
250- if err != nil {
251- return nil , fmt .Errorf ("error opening template file: %w" , err )
252- }
253- defer tmplFile .Close ()
254-
255- // Create template context
256- tmplCtx := tmpl .NewTemplateContext (opts ... )
257-
258- // Process template
259- buf := bytes .NewBuffer (nil )
260- if err := tmplCtx .InstantiateTemplate (tmplFile , buf ); err != nil {
261- return nil , fmt .Errorf ("error processing template: %w" , err )
262- }
263-
264- return buf , nil
265- }
266-
267- func (m * Main ) deploy (ctx context.Context , r io.Reader ) error {
268- // Create a multi reader to output deployment input to stdout
269- buf := bytes .NewBuffer (nil )
270- tee := io .TeeReader (r , buf )
271-
272- // Log the deployment input
273- log .Println ("Deployment input:" )
274- if _ , err := io .Copy (os .Stdout , tee ); err != nil {
275- return fmt .Errorf ("error copying deployment input: %w" , err )
276- }
277-
278- opts := []kurtosis.KurtosisDeployerOptions {
279- kurtosis .WithKurtosisBaseDir (m .cfg .baseDir ),
280- kurtosis .WithKurtosisDryRun (m .cfg .dryRun ),
281- kurtosis .WithKurtosisPackageName (m .cfg .kurtosisPackage ),
282- kurtosis .WithKurtosisEnclave (m .cfg .enclave ),
283- }
284-
285- d , err := m .newDeployer (opts ... )
286- if err != nil {
287- return fmt .Errorf ("error creating kurtosis deployer: %w" , err )
288- }
289-
290- spec , err := d .Deploy (ctx , buf )
291- if err != nil {
292- return fmt .Errorf ("error deploying kurtosis package: %w" , err )
293- }
294-
295- env , err := d .GetEnvironmentInfo (ctx , spec )
296- if err != nil {
297- return fmt .Errorf ("error getting environment: %w" , err )
298- }
299-
300- if err := writeEnvironment (m .cfg .environment , env ); err != nil {
301- return fmt .Errorf ("error writing environment: %w" , err )
302- }
303-
304- return nil
305- }
306-
307- func (m * Main ) deployFileserver (ctx context.Context , sourceDir string ) error {
308- // Create a temp dir in the fileserver package
309- baseDir := filepath .Join (m .cfg .baseDir , FILESERVER_PACKAGE )
310- if err := os .MkdirAll (baseDir , 0755 ); err != nil {
311- return fmt .Errorf ("error creating base directory: %w" , err )
312- }
313- tempDir , err := os .MkdirTemp (baseDir , "upload-content" )
314- if err != nil {
315- return fmt .Errorf ("error creating temporary directory: %w" , err )
316- }
317- defer os .RemoveAll (tempDir )
318-
319- // Copy build dir contents to tempDir
320- if err := util .CopyDir (sourceDir , tempDir ); err != nil {
321- return fmt .Errorf ("error copying directory: %w" , err )
322- }
323-
324- buf := bytes .NewBuffer (nil )
325- buf .WriteString (fmt .Sprintf ("source_path: %s\n " , filepath .Base (tempDir )))
326-
327- opts := []kurtosis.KurtosisDeployerOptions {
328- kurtosis .WithKurtosisBaseDir (m .cfg .baseDir ),
329- kurtosis .WithKurtosisDryRun (m .cfg .dryRun ),
330- kurtosis .WithKurtosisPackageName (FILESERVER_PACKAGE ),
331- kurtosis .WithKurtosisEnclave (m .cfg .enclave ),
332- }
333-
334- d , err := m .newDeployer (opts ... )
335- if err != nil {
336- return fmt .Errorf ("error creating kurtosis deployer: %w" , err )
337- }
338-
339- _ , err = d .Deploy (ctx , buf )
340- if err != nil {
341- return fmt .Errorf ("error deploying kurtosis package: %w" , err )
342- }
343-
344- return nil
345- }
346-
347- type deployer interface {
348- Deploy (ctx context.Context , input io.Reader ) (* spec.EnclaveSpec , error )
349- GetEnvironmentInfo (ctx context.Context , spec * spec.EnclaveSpec ) (* kurtosis.KurtosisEnvironment , error )
350- }
351-
35247func writeEnvironment (path string , env * kurtosis.KurtosisEnvironment ) error {
35348 out := os .Stdout
35449 if path != "" {
@@ -369,49 +64,30 @@ func writeEnvironment(path string, env *kurtosis.KurtosisEnvironment) error {
36964 return nil
37065}
37166
372- func (m * Main ) run () error {
373- ctx , cancel := context .WithCancel (context .Background ())
374- defer cancel ()
375-
376- if ! m .cfg .dryRun {
377- if err := m .engineManager .EnsureRunning (); err != nil {
378- return fmt .Errorf ("error ensuring kurtosis engine is running: %w" , err )
379- }
380- }
67+ func mainAction (c * cli.Context ) error {
68+ ctx := context .Background ()
38169
382- tmpDir , err := os . MkdirTemp ( "" , m . cfg . enclave )
70+ cfg , err := newConfig ( c )
38371 if err != nil {
384- return fmt .Errorf ("error creating temporary directory : %w" , err )
72+ return fmt .Errorf ("error parsing config : %w" , err )
38573 }
386- defer os .RemoveAll (tmpDir )
38774
388- buf , err := m .renderTemplate (tmpDir )
389- if err != nil {
390- return fmt .Errorf ("error rendering template: %w" , err )
391- }
75+ deployer := deploy .NewDeployer (
76+ deploy .WithKurtosisPackage (cfg .kurtosisPackage ),
77+ deploy .WithEnclave (cfg .enclave ),
78+ deploy .WithDryRun (cfg .dryRun ),
79+ deploy .WithKurtosisBinary (cfg .kurtosisBinary ),
80+ deploy .WithTemplateFile (cfg .templateFile ),
81+ deploy .WithDataFile (cfg .dataFile ),
82+ deploy .WithBaseDir (cfg .baseDir ),
83+ )
39284
393- // TODO: clean up consumers of static server and replace with fileserver
394- err = m .deployFileserver (ctx , tmpDir )
85+ env , err := deployer .Deploy (ctx , nil )
39586 if err != nil {
396- return fmt .Errorf ("error deploying fileserver : %w" , err )
87+ return fmt .Errorf ("error deploying environment : %w" , err )
39788 }
39889
399- return m .deploy (ctx , buf )
400- }
401-
402- func mainAction (c * cli.Context ) error {
403- cfg , err := newConfig (c )
404- if err != nil {
405- return fmt .Errorf ("error parsing config: %w" , err )
406- }
407- m := & Main {
408- cfg : cfg ,
409- newDeployer : func (opts ... kurtosis.KurtosisDeployerOptions ) (deployer , error ) {
410- return kurtosis .NewKurtosisDeployer (opts ... )
411- },
412- engineManager : engine .NewEngineManager (engine .WithKurtosisBinary (cfg .kurtosisBinary )),
413- }
414- return m .run ()
90+ return writeEnvironment (cfg .environment , env )
41591}
41692
41793func getFlags () []cli.Flag {
0 commit comments