Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
b528c3ac
Unverified
Commit
b528c3ac
authored
Jan 21, 2025
by
Yann Hodique
Committed by
GitHub
Jan 21, 2025
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore(kurtosis-devnet): add proper deploy package (#13869)
parent
8c456120
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
844 additions
and
574 deletions
+844
-574
main.go
kurtosis-devnet/cmd/main.go
+17
-341
main_test.go
kurtosis-devnet/cmd/main_test.go
+24
-233
deploy.go
kurtosis-devnet/pkg/deploy/deploy.go
+187
-0
deploy_test.go
kurtosis-devnet/pkg/deploy/deploy_test.go
+94
-0
fileserver.go
kurtosis-devnet/pkg/deploy/fileserver.go
+66
-0
fileserver_test.go
kurtosis-devnet/pkg/deploy/fileserver_test.go
+66
-0
prestate.go
kurtosis-devnet/pkg/deploy/prestate.go
+110
-0
prestate_test.go
kurtosis-devnet/pkg/deploy/prestate_test.go
+106
-0
template.go
kurtosis-devnet/pkg/deploy/template.go
+120
-0
template_test.go
kurtosis-devnet/pkg/deploy/template_test.go
+54
-0
No files found.
kurtosis-devnet/cmd/main.go
View file @
b528c3ac
This diff is collapsed.
Click to expand it.
kurtosis-devnet/cmd/main_test.go
View file @
b528c3ac
package
main
package
main
import
(
import
(
"bytes"
"context"
"encoding/json"
"io"
"os"
"os"
"path/filepath"
"path/filepath"
"testing"
"testing"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis/sources/spec"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/tmpl"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
"github.com/urfave/cli/v2"
"github.com/urfave/cli/v2"
"gopkg.in/yaml.v3"
)
)
type
mockDeployer
struct
{
dryRun
bool
}
func
(
m
*
mockDeployer
)
Deploy
(
ctx
context
.
Context
,
input
io
.
Reader
)
(
*
spec
.
EnclaveSpec
,
error
)
{
return
&
spec
.
EnclaveSpec
{},
nil
}
func
(
m
*
mockDeployer
)
GetEnvironmentInfo
(
ctx
context
.
Context
,
spec
*
spec
.
EnclaveSpec
)
(
*
kurtosis
.
KurtosisEnvironment
,
error
)
{
return
&
kurtosis
.
KurtosisEnvironment
{},
nil
}
func
newMockDeployer
(
...
kurtosis
.
KurtosisDeployerOptions
)
(
deployer
,
error
)
{
return
&
mockDeployer
{
dryRun
:
true
},
nil
}
type
mockEngineManager
struct
{}
func
(
m
*
mockEngineManager
)
EnsureRunning
()
error
{
return
nil
}
func
newTestMain
(
cfg
*
config
)
*
Main
{
return
&
Main
{
cfg
:
cfg
,
newDeployer
:
func
(
opts
...
kurtosis
.
KurtosisDeployerOptions
)
(
deployer
,
error
)
{
return
newMockDeployer
(
opts
...
)
},
engineManager
:
&
mockEngineManager
{},
}
}
func
TestParseFlags
(
t
*
testing
.
T
)
{
func
TestParseFlags
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
tests
:=
[]
struct
{
name
string
name
string
...
@@ -124,100 +85,7 @@ func TestParseFlags(t *testing.T) {
...
@@ -124,100 +85,7 @@ func TestParseFlags(t *testing.T) {
}
}
}
}
func
TestRenderTemplate
(
t
*
testing
.
T
)
{
func
TestMainFuncValidatesConfig
(
t
*
testing
.
T
)
{
// Create a temporary directory for test files
tmpDir
,
err
:=
os
.
MkdirTemp
(
""
,
"template-test"
)
require
.
NoError
(
t
,
err
)
defer
os
.
RemoveAll
(
tmpDir
)
// Create a test template file
templateContent
:=
`
name: {{.name}}
image: {{localDockerImage "test-project"}}
artifacts: {{localContractArtifacts "l1"}}`
templatePath
:=
filepath
.
Join
(
tmpDir
,
"template.yaml"
)
err
=
os
.
WriteFile
(
templatePath
,
[]
byte
(
templateContent
),
0644
)
require
.
NoError
(
t
,
err
)
// Create a test data file
dataContent
:=
`{"name": "test-deployment"}`
dataPath
:=
filepath
.
Join
(
tmpDir
,
"data.json"
)
err
=
os
.
WriteFile
(
dataPath
,
[]
byte
(
dataContent
),
0644
)
require
.
NoError
(
t
,
err
)
cfg
:=
&
config
{
templateFile
:
templatePath
,
dataFile
:
dataPath
,
enclave
:
"test-enclave"
,
dryRun
:
true
,
// Important for tests
}
m
:=
newTestMain
(
cfg
)
buf
,
err
:=
m
.
renderTemplate
(
tmpDir
)
require
.
NoError
(
t
,
err
)
// Verify template rendering
assert
.
Contains
(
t
,
buf
.
String
(),
"test-deployment"
)
assert
.
Contains
(
t
,
buf
.
String
(),
"test-project:test-enclave"
)
}
func
TestDeploy
(
t
*
testing
.
T
)
{
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
defer
cancel
()
// Create a temporary directory for the environment output
tmpDir
,
err
:=
os
.
MkdirTemp
(
""
,
"deploy-test"
)
require
.
NoError
(
t
,
err
)
defer
os
.
RemoveAll
(
tmpDir
)
envPath
:=
filepath
.
Join
(
tmpDir
,
"env.json"
)
cfg
:=
&
config
{
environment
:
envPath
,
dryRun
:
true
,
}
// Create a simple deployment configuration
deployConfig
:=
bytes
.
NewBufferString
(
`{"test": "config"}`
)
m
:=
newTestMain
(
cfg
)
err
=
m
.
deploy
(
ctx
,
deployConfig
)
require
.
NoError
(
t
,
err
)
// Verify the environment file was created
assert
.
FileExists
(
t
,
envPath
)
// Read and verify the content
content
,
err
:=
os
.
ReadFile
(
envPath
)
require
.
NoError
(
t
,
err
)
var
env
map
[
string
]
interface
{}
err
=
json
.
Unmarshal
(
content
,
&
env
)
require
.
NoError
(
t
,
err
)
}
func
TestDeployFileserver
(
t
*
testing
.
T
)
{
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
defer
cancel
()
tmpDir
,
err
:=
os
.
MkdirTemp
(
""
,
"deploy-fileserver-test"
)
require
.
NoError
(
t
,
err
)
defer
os
.
RemoveAll
(
tmpDir
)
envPath
:=
filepath
.
Join
(
tmpDir
,
"env.json"
)
cfg
:=
&
config
{
baseDir
:
tmpDir
,
environment
:
envPath
,
dryRun
:
true
,
}
m
:=
newTestMain
(
cfg
)
err
=
m
.
deployFileserver
(
ctx
,
filepath
.
Join
(
tmpDir
,
"fileserver"
))
require
.
NoError
(
t
,
err
)
}
func
TestMainFunc
(
t
*
testing
.
T
)
{
// Create a temporary directory for test files
// Create a temporary directory for test files
tmpDir
,
err
:=
os
.
MkdirTemp
(
""
,
"main-test"
)
tmpDir
,
err
:=
os
.
MkdirTemp
(
""
,
"main-test"
)
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
...
@@ -231,111 +99,34 @@ func TestMainFunc(t *testing.T) {
...
@@ -231,111 +99,34 @@ func TestMainFunc(t *testing.T) {
// Create environment output path
// Create environment output path
envPath
:=
filepath
.
Join
(
tmpDir
,
"env.json"
)
envPath
:=
filepath
.
Join
(
tmpDir
,
"env.json"
)
cfg
:=
&
config
{
app
:=
&
cli
.
App
{
templateFile
:
templatePath
,
Flags
:
getFlags
(),
environment
:
envPath
,
Action
:
func
(
c
*
cli
.
Context
)
error
{
dryRun
:
true
,
cfg
,
err
:=
newConfig
(
c
)
}
if
err
!=
nil
{
return
err
m
:=
newTestMain
(
cfg
)
}
err
=
m
.
run
()
require
.
NoError
(
t
,
err
)
// Verify the environment file was created
assert
.
FileExists
(
t
,
envPath
)
}
func
TestLocalPrestate
(
t
*
testing
.
T
)
{
// Create a temporary directory for test files
tmpDir
,
err
:=
os
.
MkdirTemp
(
""
,
"prestate-test"
)
require
.
NoError
(
t
,
err
)
defer
os
.
RemoveAll
(
tmpDir
)
// Create a mock justfile
// Verify config values
err
=
os
.
WriteFile
(
filepath
.
Join
(
tmpDir
,
"justfile"
),
[]
byte
(
`
assert
.
Equal
(
t
,
templatePath
,
cfg
.
templateFile
)
_prestate-build target:
assert
.
Equal
(
t
,
envPath
,
cfg
.
environment
)
@echo "Mock prestate build"
assert
.
True
(
t
,
cfg
.
dryRun
)
`
),
0644
)
require
.
NoError
(
t
,
err
)
tests
:=
[]
struct
{
// Create an empty environment file to simulate successful deployment
name
string
return
os
.
WriteFile
(
envPath
,
[]
byte
(
"{}"
),
0644
)
dryRun
bool
wantErr
bool
}{
{
name
:
"dry run mode"
,
dryRun
:
true
,
wantErr
:
false
,
},
{
name
:
"normal mode"
,
dryRun
:
false
,
wantErr
:
false
,
},
},
}
}
for
_
,
tt
:=
range
tests
{
args
:=
[]
string
{
t
.
Run
(
tt
.
name
,
func
(
t
*
testing
.
T
)
{
"prog"
,
cfg
:=
&
config
{
"--template"
,
templatePath
,
baseDir
:
tmpDir
,
"--environment"
,
envPath
,
dryRun
:
tt
.
dryRun
,
"--dry-run"
,
}
}
m
:=
newTestMain
(
cfg
)
tmpDir
,
err
:=
os
.
MkdirTemp
(
""
,
"prestate-test"
)
require
.
NoError
(
t
,
err
)
defer
os
.
RemoveAll
(
tmpDir
)
// Create template context with just the prestate function
tmplCtx
:=
tmpl
.
NewTemplateContext
(
m
.
localPrestateOption
(
tmpDir
))
// Test template with multiple calls to localPrestate
template
:=
`first:
url: {{(localPrestate).URL}}
hashes:
game: {{index (localPrestate).Hashes "game"}}
proof: {{index (localPrestate).Hashes "proof"}}
second:
url: {{(localPrestate).URL}}
hashes:
game: {{index (localPrestate).Hashes "game"}}
proof: {{index (localPrestate).Hashes "proof"}}`
buf
:=
bytes
.
NewBuffer
(
nil
)
err
=
tmplCtx
.
InstantiateTemplate
(
bytes
.
NewBufferString
(
template
),
buf
)
if
tt
.
wantErr
{
assert
.
Error
(
t
,
err
)
return
}
require
.
NoError
(
t
,
err
)
// Verify the output is valid YAML and contains the static path
output
:=
buf
.
String
()
assert
.
Contains
(
t
,
output
,
"url: http://fileserver/proofs/op-program/cannon"
)
// Verify both calls return the same values
var
result
struct
{
First
struct
{
URL
string
`yaml:"url"`
Hashes
map
[
string
]
string
`yaml:"hashes"`
}
`yaml:"first"`
Second
struct
{
URL
string
`yaml:"url"`
Hashes
map
[
string
]
string
`yaml:"hashes"`
}
`yaml:"second"`
}
err
=
yaml
.
Unmarshal
(
buf
.
Bytes
(),
&
result
)
require
.
NoError
(
t
,
err
)
// Check that both calls returned identical results
err
=
app
.
Run
(
args
)
assert
.
Equal
(
t
,
result
.
First
.
URL
,
result
.
Second
.
URL
,
"URLs should match"
)
require
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
result
.
First
.
Hashes
,
result
.
Second
.
Hashes
,
"Hashes should match"
)
// Verify the directory was created only once
// Verify the environment file was created
prestateDir
:=
filepath
.
Join
(
tmpDir
,
"proofs"
,
"op-program"
,
"cannon"
)
assert
.
FileExists
(
t
,
envPath
)
assert
.
DirExists
(
t
,
prestateDir
)
})
}
}
}
kurtosis-devnet/pkg/deploy/deploy.go
0 → 100644
View file @
b528c3ac
package
deploy
import
(
"bytes"
"context"
"fmt"
"io"
"log"
"os"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis/api/engine"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis/sources/spec"
)
type
EngineManager
interface
{
EnsureRunning
()
error
}
type
deployer
interface
{
Deploy
(
ctx
context
.
Context
,
input
io
.
Reader
)
(
*
spec
.
EnclaveSpec
,
error
)
GetEnvironmentInfo
(
ctx
context
.
Context
,
spec
*
spec
.
EnclaveSpec
)
(
*
kurtosis
.
KurtosisEnvironment
,
error
)
}
type
DeployerFunc
func
(
opts
...
kurtosis
.
KurtosisDeployerOptions
)
(
deployer
,
error
)
type
DeployerOption
func
(
*
Deployer
)
type
Deployer
struct
{
baseDir
string
dryRun
bool
kurtosisPkg
string
enclave
string
kurtosisBinary
string
ktDeployer
DeployerFunc
engineManager
EngineManager
templateFile
string
dataFile
string
}
func
WithKurtosisDeployer
(
ktDeployer
DeployerFunc
)
DeployerOption
{
return
func
(
d
*
Deployer
)
{
d
.
ktDeployer
=
ktDeployer
}
}
func
WithEngineManager
(
engineManager
EngineManager
)
DeployerOption
{
return
func
(
d
*
Deployer
)
{
d
.
engineManager
=
engineManager
}
}
func
WithKurtosisBinary
(
kurtosisBinary
string
)
DeployerOption
{
return
func
(
d
*
Deployer
)
{
d
.
kurtosisBinary
=
kurtosisBinary
}
}
func
WithKurtosisPackage
(
kurtosisPkg
string
)
DeployerOption
{
return
func
(
d
*
Deployer
)
{
d
.
kurtosisPkg
=
kurtosisPkg
}
}
func
WithTemplateFile
(
templateFile
string
)
DeployerOption
{
return
func
(
d
*
Deployer
)
{
d
.
templateFile
=
templateFile
}
}
func
WithDataFile
(
dataFile
string
)
DeployerOption
{
return
func
(
d
*
Deployer
)
{
d
.
dataFile
=
dataFile
}
}
func
WithBaseDir
(
baseDir
string
)
DeployerOption
{
return
func
(
d
*
Deployer
)
{
d
.
baseDir
=
baseDir
}
}
func
WithDryRun
(
dryRun
bool
)
DeployerOption
{
return
func
(
d
*
Deployer
)
{
d
.
dryRun
=
dryRun
}
}
func
WithEnclave
(
enclave
string
)
DeployerOption
{
return
func
(
d
*
Deployer
)
{
d
.
enclave
=
enclave
}
}
func
NewDeployer
(
opts
...
DeployerOption
)
*
Deployer
{
d
:=
&
Deployer
{
kurtosisBinary
:
"kurtosis"
,
ktDeployer
:
func
(
opts
...
kurtosis
.
KurtosisDeployerOptions
)
(
deployer
,
error
)
{
return
kurtosis
.
NewKurtosisDeployer
(
opts
...
)
},
}
for
_
,
opt
:=
range
opts
{
opt
(
d
)
}
if
d
.
engineManager
==
nil
{
d
.
engineManager
=
engine
.
NewEngineManager
(
engine
.
WithKurtosisBinary
(
d
.
kurtosisBinary
))
}
return
d
}
func
(
d
*
Deployer
)
deployEnvironment
(
ctx
context
.
Context
,
r
io
.
Reader
)
(
*
kurtosis
.
KurtosisEnvironment
,
error
)
{
// Create a multi reader to output deployment input to stdout
buf
:=
bytes
.
NewBuffer
(
nil
)
tee
:=
io
.
TeeReader
(
r
,
buf
)
// Log the deployment input
log
.
Println
(
"Deployment input:"
)
if
_
,
err
:=
io
.
Copy
(
os
.
Stdout
,
tee
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error copying deployment input: %w"
,
err
)
}
opts
:=
[]
kurtosis
.
KurtosisDeployerOptions
{
kurtosis
.
WithKurtosisBaseDir
(
d
.
baseDir
),
kurtosis
.
WithKurtosisDryRun
(
d
.
dryRun
),
kurtosis
.
WithKurtosisPackageName
(
d
.
kurtosisPkg
),
kurtosis
.
WithKurtosisEnclave
(
d
.
enclave
),
}
ktd
,
err
:=
d
.
ktDeployer
(
opts
...
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error creating kurtosis deployer: %w"
,
err
)
}
spec
,
err
:=
ktd
.
Deploy
(
ctx
,
buf
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error deploying kurtosis package: %w"
,
err
)
}
return
ktd
.
GetEnvironmentInfo
(
ctx
,
spec
)
}
func
(
d
*
Deployer
)
renderTemplate
(
buildDir
string
,
urlBuilder
func
(
path
...
string
)
string
)
(
*
bytes
.
Buffer
,
error
)
{
t
:=
&
Templater
{
baseDir
:
d
.
baseDir
,
dryRun
:
d
.
dryRun
,
enclave
:
d
.
enclave
,
templateFile
:
d
.
templateFile
,
dataFile
:
d
.
dataFile
,
buildDir
:
buildDir
,
urlBuilder
:
urlBuilder
,
}
return
t
.
Render
()
}
func
(
d
*
Deployer
)
Deploy
(
ctx
context
.
Context
,
r
io
.
Reader
)
(
*
kurtosis
.
KurtosisEnvironment
,
error
)
{
if
!
d
.
dryRun
{
if
err
:=
d
.
engineManager
.
EnsureRunning
();
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error ensuring kurtosis engine is running: %w"
,
err
)
}
}
tmpDir
,
err
:=
os
.
MkdirTemp
(
""
,
d
.
enclave
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error creating temporary directory: %w"
,
err
)
}
defer
os
.
RemoveAll
(
tmpDir
)
srv
:=
&
FileServer
{
baseDir
:
d
.
baseDir
,
dryRun
:
d
.
dryRun
,
enclave
:
d
.
enclave
,
deployer
:
d
.
ktDeployer
,
}
buf
,
err
:=
d
.
renderTemplate
(
tmpDir
,
srv
.
URL
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error rendering template: %w"
,
err
)
}
if
err
:=
srv
.
Deploy
(
ctx
,
tmpDir
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error deploying fileserver: %w"
,
err
)
}
return
d
.
deployEnvironment
(
ctx
,
buf
)
}
kurtosis-devnet/pkg/deploy/deploy_test.go
0 → 100644
View file @
b528c3ac
package
deploy
import
(
"bytes"
"context"
"encoding/json"
"io"
"os"
"path/filepath"
"testing"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis/sources/spec"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// mockDeployerForTest implements the deployer interface for testing
type
mockDeployerForTest
struct
{
baseDir
string
}
func
(
m
*
mockDeployerForTest
)
Deploy
(
ctx
context
.
Context
,
input
io
.
Reader
)
(
*
spec
.
EnclaveSpec
,
error
)
{
// Create a mock env.json file
envPath
:=
filepath
.
Join
(
m
.
baseDir
,
"env.json"
)
mockEnv
:=
map
[
string
]
interface
{}{
"test"
:
"value"
,
}
data
,
err
:=
json
.
Marshal
(
mockEnv
)
if
err
!=
nil
{
return
nil
,
err
}
if
err
:=
os
.
WriteFile
(
envPath
,
data
,
0644
);
err
!=
nil
{
return
nil
,
err
}
return
&
spec
.
EnclaveSpec
{},
nil
}
func
(
m
*
mockDeployerForTest
)
GetEnvironmentInfo
(
ctx
context
.
Context
,
spec
*
spec
.
EnclaveSpec
)
(
*
kurtosis
.
KurtosisEnvironment
,
error
)
{
return
&
kurtosis
.
KurtosisEnvironment
{},
nil
}
func
TestDeploy
(
t
*
testing
.
T
)
{
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
defer
cancel
()
// Create a temporary directory for the environment output
tmpDir
,
err
:=
os
.
MkdirTemp
(
""
,
"deploy-test"
)
require
.
NoError
(
t
,
err
)
defer
os
.
RemoveAll
(
tmpDir
)
// Create a simple template file
templatePath
:=
filepath
.
Join
(
tmpDir
,
"template.yaml"
)
err
=
os
.
WriteFile
(
templatePath
,
[]
byte
(
"test: {{ .Config }}"
),
0644
)
require
.
NoError
(
t
,
err
)
// Create a simple data file
dataPath
:=
filepath
.
Join
(
tmpDir
,
"data.json"
)
err
=
os
.
WriteFile
(
dataPath
,
[]
byte
(
`{"Config": "value"}`
),
0644
)
require
.
NoError
(
t
,
err
)
envPath
:=
filepath
.
Join
(
tmpDir
,
"env.json"
)
// Create a simple deployment configuration
deployConfig
:=
bytes
.
NewBufferString
(
`{"test": "config"}`
)
// Create a mock deployer function
mockDeployerFunc
:=
func
(
opts
...
kurtosis
.
KurtosisDeployerOptions
)
(
deployer
,
error
)
{
return
&
mockDeployerForTest
{
baseDir
:
tmpDir
},
nil
}
d
:=
NewDeployer
(
WithBaseDir
(
tmpDir
),
WithKurtosisDeployer
(
mockDeployerFunc
),
WithDryRun
(
true
),
WithTemplateFile
(
templatePath
),
WithDataFile
(
dataPath
),
)
env
,
err
:=
d
.
Deploy
(
ctx
,
deployConfig
)
require
.
NoError
(
t
,
err
)
require
.
NotNil
(
t
,
env
)
// Verify the environment file was created
assert
.
FileExists
(
t
,
envPath
)
// Read and verify the content
content
,
err
:=
os
.
ReadFile
(
envPath
)
require
.
NoError
(
t
,
err
)
var
envData
map
[
string
]
interface
{}
err
=
json
.
Unmarshal
(
content
,
&
envData
)
require
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
"value"
,
envData
[
"test"
])
}
kurtosis-devnet/pkg/deploy/fileserver.go
0 → 100644
View file @
b528c3ac
package
deploy
import
(
"bytes"
"context"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/util"
)
const
FILESERVER_PACKAGE
=
"fileserver"
type
FileServer
struct
{
baseDir
string
enclave
string
dryRun
bool
deployer
DeployerFunc
}
func
(
f
*
FileServer
)
URL
(
path
...
string
)
string
{
return
fmt
.
Sprintf
(
"http://%s/%s"
,
FILESERVER_PACKAGE
,
strings
.
Join
(
path
,
"/"
))
}
func
(
f
*
FileServer
)
Deploy
(
ctx
context
.
Context
,
sourceDir
string
)
error
{
// Create a temp dir in the fileserver package
baseDir
:=
filepath
.
Join
(
f
.
baseDir
,
FILESERVER_PACKAGE
)
if
err
:=
os
.
MkdirAll
(
baseDir
,
0755
);
err
!=
nil
{
return
fmt
.
Errorf
(
"error creating base directory: %w"
,
err
)
}
tempDir
,
err
:=
os
.
MkdirTemp
(
baseDir
,
"upload-content"
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"error creating temporary directory: %w"
,
err
)
}
defer
os
.
RemoveAll
(
tempDir
)
// Copy build dir contents to tempDir
if
err
:=
util
.
CopyDir
(
sourceDir
,
tempDir
);
err
!=
nil
{
return
fmt
.
Errorf
(
"error copying directory: %w"
,
err
)
}
buf
:=
bytes
.
NewBuffer
(
nil
)
buf
.
WriteString
(
fmt
.
Sprintf
(
"source_path: %s
\n
"
,
filepath
.
Base
(
tempDir
)))
opts
:=
[]
kurtosis
.
KurtosisDeployerOptions
{
kurtosis
.
WithKurtosisBaseDir
(
f
.
baseDir
),
kurtosis
.
WithKurtosisDryRun
(
f
.
dryRun
),
kurtosis
.
WithKurtosisPackageName
(
FILESERVER_PACKAGE
),
kurtosis
.
WithKurtosisEnclave
(
f
.
enclave
),
}
d
,
err
:=
f
.
deployer
(
opts
...
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"error creating kurtosis deployer: %w"
,
err
)
}
_
,
err
=
d
.
Deploy
(
ctx
,
buf
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"error deploying kurtosis package: %w"
,
err
)
}
return
nil
}
kurtosis-devnet/pkg/deploy/fileserver_test.go
0 → 100644
View file @
b528c3ac
package
deploy
import
(
"context"
"io"
"os"
"path/filepath"
"testing"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/kurtosis/sources/spec"
"github.com/stretchr/testify/require"
)
func
TestDeployFileserver
(
t
*
testing
.
T
)
{
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
defer
cancel
()
tmpDir
,
err
:=
os
.
MkdirTemp
(
""
,
"deploy-fileserver-test"
)
require
.
NoError
(
t
,
err
)
defer
os
.
RemoveAll
(
tmpDir
)
// Create a mock deployer function
mockDeployerFunc
:=
func
(
opts
...
kurtosis
.
KurtosisDeployerOptions
)
(
deployer
,
error
)
{
return
&
mockDeployer
{},
nil
}
testCases
:=
[]
struct
{
name
string
fs
*
FileServer
shouldError
bool
}{
{
name
:
"successful deployment"
,
fs
:
&
FileServer
{
baseDir
:
tmpDir
,
enclave
:
"test-enclave"
,
dryRun
:
true
,
deployer
:
mockDeployerFunc
,
},
shouldError
:
false
,
},
}
for
_
,
tc
:=
range
testCases
{
t
.
Run
(
tc
.
name
,
func
(
t
*
testing
.
T
)
{
err
:=
tc
.
fs
.
Deploy
(
ctx
,
filepath
.
Join
(
tmpDir
,
"fileserver"
))
if
tc
.
shouldError
{
require
.
Error
(
t
,
err
)
}
else
{
require
.
NoError
(
t
,
err
)
}
})
}
}
// mockDeployer implements the deployer interface for testing
type
mockDeployer
struct
{}
func
(
m
*
mockDeployer
)
Deploy
(
ctx
context
.
Context
,
input
io
.
Reader
)
(
*
spec
.
EnclaveSpec
,
error
)
{
return
&
spec
.
EnclaveSpec
{},
nil
}
func
(
m
*
mockDeployer
)
GetEnvironmentInfo
(
ctx
context
.
Context
,
spec
*
spec
.
EnclaveSpec
)
(
*
kurtosis
.
KurtosisEnvironment
,
error
)
{
return
&
kurtosis
.
KurtosisEnvironment
{},
nil
}
kurtosis-devnet/pkg/deploy/prestate.go
0 → 100644
View file @
b528c3ac
package
deploy
import
(
"encoding/json"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/build"
)
type
PrestateInfo
struct
{
URL
string
`json:"url"`
Hashes
map
[
string
]
string
`json:"hashes"`
}
type
localPrestateHolder
struct
{
info
*
PrestateInfo
baseDir
string
buildDir
string
dryRun
bool
builder
*
build
.
PrestateBuilder
urlBuilder
func
(
path
...
string
)
string
}
func
(
h
*
localPrestateHolder
)
GetPrestateInfo
()
(
*
PrestateInfo
,
error
)
{
if
h
.
info
!=
nil
{
return
h
.
info
,
nil
}
prestatePath
:=
[]
string
{
"proofs"
,
"op-program"
,
"cannon"
}
prestateURL
:=
h
.
urlBuilder
(
prestatePath
...
)
// Create build directory with the final path structure
buildDir
:=
filepath
.
Join
(
append
([]
string
{
h
.
buildDir
},
prestatePath
...
)
...
)
if
err
:=
os
.
MkdirAll
(
buildDir
,
0755
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to create prestate build directory: %w"
,
err
)
}
info
:=
&
PrestateInfo
{
URL
:
prestateURL
,
Hashes
:
make
(
map
[
string
]
string
),
}
if
h
.
dryRun
{
h
.
info
=
info
return
info
,
nil
}
// Map of known file prefixes to their keys
fileToKey
:=
map
[
string
]
string
{
"prestate-proof.json"
:
"prestate"
,
"prestate-proof-mt64.json"
:
"prestate_mt64"
,
"prestate-proof-mt.json"
:
"prestate_mt"
,
"prestate-proof-interop.json"
:
"prestate_interop"
,
}
// Build all prestate files directly in the target directory
if
err
:=
h
.
builder
.
Build
(
buildDir
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to build prestates: %w"
,
err
)
}
// Find and process all prestate files
matches
,
err
:=
filepath
.
Glob
(
filepath
.
Join
(
buildDir
,
"prestate-proof*.json"
))
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to find prestate files: %w"
,
err
)
}
// Process each file to rename it to its hash
for
_
,
filePath
:=
range
matches
{
content
,
err
:=
os
.
ReadFile
(
filePath
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to read prestate %s: %w"
,
filepath
.
Base
(
filePath
),
err
)
}
var
data
struct
{
Pre
string
`json:"pre"`
}
if
err
:=
json
.
Unmarshal
(
content
,
&
data
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to parse prestate %s: %w"
,
filepath
.
Base
(
filePath
),
err
)
}
// Store hash with its corresponding key
if
key
,
exists
:=
fileToKey
[
filepath
.
Base
(
filePath
)];
exists
{
info
.
Hashes
[
key
]
=
data
.
Pre
}
// Rename files to hash-based names
newFileName
:=
data
.
Pre
+
".json"
hashedPath
:=
filepath
.
Join
(
buildDir
,
newFileName
)
if
err
:=
os
.
Rename
(
filePath
,
hashedPath
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to rename prestate %s: %w"
,
filepath
.
Base
(
filePath
),
err
)
}
log
.
Printf
(
"%s available at: %s/%s
\n
"
,
filepath
.
Base
(
filePath
),
prestateURL
,
newFileName
)
// Rename the corresponding binary file
binFilePath
:=
strings
.
Replace
(
strings
.
TrimSuffix
(
filePath
,
".json"
),
"-proof"
,
""
,
1
)
+
".bin.gz"
newBinFileName
:=
data
.
Pre
+
".bin.gz"
binHashedPath
:=
filepath
.
Join
(
buildDir
,
newBinFileName
)
if
err
:=
os
.
Rename
(
binFilePath
,
binHashedPath
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to rename prestate %s: %w"
,
filepath
.
Base
(
binFilePath
),
err
)
}
log
.
Printf
(
"%s available at: %s/%s
\n
"
,
filepath
.
Base
(
binFilePath
),
prestateURL
,
newBinFileName
)
}
h
.
info
=
info
return
info
,
nil
}
kurtosis-devnet/pkg/deploy/prestate_test.go
0 → 100644
View file @
b528c3ac
package
deploy
import
(
"bytes"
"os"
"path/filepath"
"strings"
"testing"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/tmpl"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
)
func
TestLocalPrestate
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
name
string
dryRun
bool
wantErr
bool
}{
{
name
:
"dry run mode"
,
dryRun
:
true
,
wantErr
:
false
,
},
{
name
:
"normal mode"
,
dryRun
:
false
,
wantErr
:
false
,
},
}
for
_
,
tt
:=
range
tests
{
t
.
Run
(
tt
.
name
,
func
(
t
*
testing
.
T
)
{
tmpDir
,
err
:=
os
.
MkdirTemp
(
""
,
"prestate-test"
)
require
.
NoError
(
t
,
err
)
defer
os
.
RemoveAll
(
tmpDir
)
// Create a mock justfile for each test case
err
=
os
.
WriteFile
(
filepath
.
Join
(
tmpDir
,
"justfile"
),
[]
byte
(
`
_prestate-build target:
@echo "Mock prestate build"
`
),
0644
)
require
.
NoError
(
t
,
err
)
templater
:=
&
Templater
{
baseDir
:
tmpDir
,
dryRun
:
tt
.
dryRun
,
buildDir
:
tmpDir
,
urlBuilder
:
func
(
path
...
string
)
string
{
return
"http://fileserver/"
+
strings
.
Join
(
path
,
"/"
)
},
}
// Create template context with just the prestate function
tmplCtx
:=
tmpl
.
NewTemplateContext
(
templater
.
localPrestateOption
())
// Test template with multiple calls to localPrestate
template
:=
`first:
url: {{(localPrestate).URL}}
hashes:
game: {{index (localPrestate).Hashes "game"}}
proof: {{index (localPrestate).Hashes "proof"}}
second:
url: {{(localPrestate).URL}}
hashes:
game: {{index (localPrestate).Hashes "game"}}
proof: {{index (localPrestate).Hashes "proof"}}`
buf
:=
bytes
.
NewBuffer
(
nil
)
err
=
tmplCtx
.
InstantiateTemplate
(
bytes
.
NewBufferString
(
template
),
buf
)
if
tt
.
wantErr
{
assert
.
Error
(
t
,
err
)
return
}
require
.
NoError
(
t
,
err
)
// Verify the output is valid YAML and contains the static path
output
:=
buf
.
String
()
assert
.
Contains
(
t
,
output
,
"url: http://fileserver/proofs/op-program/cannon"
)
// Verify both calls return the same values
var
result
struct
{
First
struct
{
URL
string
`yaml:"url"`
Hashes
map
[
string
]
string
`yaml:"hashes"`
}
`yaml:"first"`
Second
struct
{
URL
string
`yaml:"url"`
Hashes
map
[
string
]
string
`yaml:"hashes"`
}
`yaml:"second"`
}
err
=
yaml
.
Unmarshal
(
buf
.
Bytes
(),
&
result
)
require
.
NoError
(
t
,
err
)
// Check that both calls returned identical results
assert
.
Equal
(
t
,
result
.
First
.
URL
,
result
.
Second
.
URL
,
"URLs should match"
)
assert
.
Equal
(
t
,
result
.
First
.
Hashes
,
result
.
Second
.
Hashes
,
"Hashes should match"
)
// Verify the directory was created only once
prestateDir
:=
filepath
.
Join
(
tmpDir
,
"proofs"
,
"op-program"
,
"cannon"
)
assert
.
DirExists
(
t
,
prestateDir
)
})
}
}
kurtosis-devnet/pkg/deploy/template.go
0 → 100644
View file @
b528c3ac
package
deploy
import
(
"bytes"
"encoding/json"
"fmt"
"log"
"os"
"path/filepath"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/build"
"github.com/ethereum-optimism/optimism/kurtosis-devnet/pkg/tmpl"
)
type
Templater
struct
{
enclave
string
dryRun
bool
baseDir
string
templateFile
string
dataFile
string
buildDir
string
urlBuilder
func
(
path
...
string
)
string
}
func
(
f
*
Templater
)
localDockerImageOption
()
tmpl
.
TemplateContextOptions
{
dockerBuilder
:=
build
.
NewDockerBuilder
(
build
.
WithDockerBaseDir
(
f
.
baseDir
),
build
.
WithDockerDryRun
(
f
.
dryRun
),
)
imageTag
:=
func
(
projectName
string
)
string
{
return
fmt
.
Sprintf
(
"%s:%s"
,
projectName
,
f
.
enclave
)
}
return
tmpl
.
WithFunction
(
"localDockerImage"
,
func
(
projectName
string
)
(
string
,
error
)
{
return
dockerBuilder
.
Build
(
projectName
,
imageTag
(
projectName
))
})
}
func
(
f
*
Templater
)
localContractArtifactsOption
()
tmpl
.
TemplateContextOptions
{
contractsBundle
:=
fmt
.
Sprintf
(
"contracts-bundle-%s.tar.gz"
,
f
.
enclave
)
contractsBundlePath
:=
func
(
_
string
)
string
{
return
filepath
.
Join
(
f
.
buildDir
,
contractsBundle
)
}
contractsURL
:=
f
.
urlBuilder
(
contractsBundle
)
contractBuilder
:=
build
.
NewContractBuilder
(
build
.
WithContractBaseDir
(
f
.
baseDir
),
build
.
WithContractDryRun
(
f
.
dryRun
),
)
return
tmpl
.
WithFunction
(
"localContractArtifacts"
,
func
(
layer
string
)
(
string
,
error
)
{
bundlePath
:=
contractsBundlePath
(
layer
)
if
err
:=
contractBuilder
.
Build
(
layer
,
bundlePath
);
err
!=
nil
{
return
""
,
err
}
log
.
Printf
(
"%s: contract artifacts available at: %s
\n
"
,
layer
,
contractsURL
)
return
contractsURL
,
nil
})
}
func
(
f
*
Templater
)
localPrestateOption
()
tmpl
.
TemplateContextOptions
{
holder
:=
&
localPrestateHolder
{
baseDir
:
f
.
baseDir
,
buildDir
:
f
.
buildDir
,
dryRun
:
f
.
dryRun
,
builder
:
build
.
NewPrestateBuilder
(
build
.
WithPrestateBaseDir
(
f
.
baseDir
),
build
.
WithPrestateDryRun
(
f
.
dryRun
),
),
urlBuilder
:
f
.
urlBuilder
,
}
return
tmpl
.
WithFunction
(
"localPrestate"
,
func
()
(
*
PrestateInfo
,
error
)
{
return
holder
.
GetPrestateInfo
()
})
}
func
(
f
*
Templater
)
Render
()
(
*
bytes
.
Buffer
,
error
)
{
opts
:=
[]
tmpl
.
TemplateContextOptions
{
f
.
localDockerImageOption
(),
f
.
localContractArtifactsOption
(),
f
.
localPrestateOption
(),
tmpl
.
WithBaseDir
(
f
.
baseDir
),
}
// Read and parse the data file if provided
if
f
.
dataFile
!=
""
{
data
,
err
:=
os
.
ReadFile
(
f
.
dataFile
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error reading data file: %w"
,
err
)
}
var
templateData
map
[
string
]
interface
{}
if
err
:=
json
.
Unmarshal
(
data
,
&
templateData
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error parsing JSON data: %w"
,
err
)
}
opts
=
append
(
opts
,
tmpl
.
WithData
(
templateData
))
}
// Open template file
tmplFile
,
err
:=
os
.
Open
(
f
.
templateFile
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error opening template file: %w"
,
err
)
}
defer
tmplFile
.
Close
()
// Create template context
tmplCtx
:=
tmpl
.
NewTemplateContext
(
opts
...
)
// Process template
buf
:=
bytes
.
NewBuffer
(
nil
)
if
err
:=
tmplCtx
.
InstantiateTemplate
(
tmplFile
,
buf
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error processing template: %w"
,
err
)
}
return
buf
,
nil
}
kurtosis-devnet/pkg/deploy/template_test.go
0 → 100644
View file @
b528c3ac
package
deploy
import
(
"os"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func
TestRenderTemplate
(
t
*
testing
.
T
)
{
// Create a temporary directory for test files
tmpDir
,
err
:=
os
.
MkdirTemp
(
""
,
"template-test"
)
require
.
NoError
(
t
,
err
)
defer
os
.
RemoveAll
(
tmpDir
)
// Create a test template file
templateContent
:=
`
name: {{.name}}
image: {{localDockerImage "test-project"}}
artifacts: {{localContractArtifacts "l1"}}`
templatePath
:=
filepath
.
Join
(
tmpDir
,
"template.yaml"
)
err
=
os
.
WriteFile
(
templatePath
,
[]
byte
(
templateContent
),
0644
)
require
.
NoError
(
t
,
err
)
// Create a test data file
dataContent
:=
`{"name": "test-deployment"}`
dataPath
:=
filepath
.
Join
(
tmpDir
,
"data.json"
)
err
=
os
.
WriteFile
(
dataPath
,
[]
byte
(
dataContent
),
0644
)
require
.
NoError
(
t
,
err
)
// Create a Templater instance
templater
:=
&
Templater
{
enclave
:
"test-enclave"
,
dryRun
:
true
,
baseDir
:
tmpDir
,
templateFile
:
templatePath
,
dataFile
:
dataPath
,
buildDir
:
tmpDir
,
urlBuilder
:
func
(
path
...
string
)
string
{
return
"http://localhost:8080/"
+
strings
.
Join
(
path
,
"/"
)
},
}
buf
,
err
:=
templater
.
Render
()
require
.
NoError
(
t
,
err
)
// Verify template rendering
assert
.
Contains
(
t
,
buf
.
String
(),
"test-deployment"
)
assert
.
Contains
(
t
,
buf
.
String
(),
"test-project:test-enclave"
)
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment