Skip to content

Commit 49d7ed8

Browse files
authored
Merge pull request #13 from crytic/7-speedy-pushes
[WIP] 7 speedy pushes
2 parents 5734037 + 64cf848 commit 49d7ed8

File tree

7 files changed

+153
-40
lines changed

7 files changed

+153
-40
lines changed

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
contents: read
2929
pull-requests: write
3030
steps:
31-
- uses: coderabbitai/ai-pr-reviewer@d7f9486e8bfddc6e55f9879d4e93b8eaac6f120f # v1.16.0
31+
- uses: coderabbitai/ai-pr-reviewer@44244a9e06f5acf72a93f661c7dbb8d8d808143d # v1.16.2
3232
env:
3333
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3434
OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
.direnv/
22
.env
3+
.vscode
34
.vscode/
45
bin/
56
dist/
7+
example/input.zip
68
result
7-
.vscode

cmd/cloudexec/launch.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ func InitLaunchConfig() error {
4444

4545
// Write the default launch config to the file
4646
_, err = launchConfigFile.WriteString(`
47-
4847
# Set the directory to upload to the droplet.
4948
[input]
5049
directory = ""
@@ -124,7 +123,7 @@ func Launch(user *user.User, config config.Config, dropletSize string, dropletRe
124123
// upload local files to the bucket
125124
sourcePath := lc.Input.Directory // TODO: verify that this path exists & throw informative error if not
126125
destPath := fmt.Sprintf("job-%v", thisJobId)
127-
fmt.Printf("Uploading contents of directory %s to bucket %s/%s...\n", sourcePath, bucketName, destPath)
126+
fmt.Printf("Compressing and uploading contents of directory %s to bucket %s/%s...\n", sourcePath, bucketName, destPath)
128127
err = UploadDirectoryToSpaces(config, bucketName, sourcePath, destPath)
129128
if err != nil {
130129
return fmt.Errorf("Failed to upload files: %w", err)

cmd/cloudexec/main.go

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ func main() {
7575
return nil
7676
},
7777
},
78+
{
79+
Name: "init",
80+
Usage: "Create a new cloudexec.toml launch configuration in the current directory",
81+
Action: func(c *cli.Context) error {
82+
err := InitLaunchConfig()
83+
if err != nil {
84+
return err
85+
}
86+
return nil
87+
},
88+
},
7889
{
7990
Name: "launch",
8091
Usage: "Launch a droplet and start a job",
@@ -95,19 +106,6 @@ func main() {
95106
Usage: "Optional droplet region",
96107
},
97108
},
98-
Subcommands: []*cli.Command{
99-
{
100-
Name: "init",
101-
Usage: "Create a new cloudexec.toml launch configuration in the current directory",
102-
Action: func(c *cli.Context) error {
103-
err := InitLaunchConfig()
104-
if err != nil {
105-
return err
106-
}
107-
return nil
108-
},
109-
},
110-
},
111109
Action: func(c *cli.Context) error {
112110
// Abort on configuration error
113111
if configErr != nil {

cmd/cloudexec/push.go

Lines changed: 113 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,141 @@
11
package main
22

33
import (
4+
"archive/zip"
45
"fmt"
6+
"io"
57
"os"
68
"path/filepath"
79

810
"github.com/crytic/cloudexec/pkg/config"
911
"github.com/crytic/cloudexec/pkg/s3"
1012
)
1113

12-
func UploadDirectoryToSpaces(config config.Config, bucketName string, sourcePath string, destPath string) error {
13-
// Walk the directory and upload files recursively
14-
return filepath.Walk(sourcePath, func(path string, info os.FileInfo, err error) error {
14+
func UploadDirectoryToSpaces(config config.Config, bucket string, sourcePath string, destPath string) error {
15+
// Compute the path for the zipped archive of sourcePath
16+
zipFileName := "input.zip"
17+
zipFilePath := filepath.Join(os.TempDir(), zipFileName)
18+
19+
// Create a file where we will write the zipped archive
20+
fmt.Printf("Creating zipped archive at %s\n", zipFilePath)
21+
zipFile, err := os.Create(zipFilePath)
22+
if err != nil {
23+
return err
24+
}
25+
defer zipFile.Close()
26+
27+
// Create a new zip writer
28+
zipWriter := zip.NewWriter(zipFile)
29+
defer zipWriter.Close()
30+
31+
// Walk the directory and recursively add files to the zipped archive
32+
err = filepath.Walk(sourcePath, func(path string, info os.FileInfo, err error) error {
33+
target := path
1534
if err != nil {
1635
return err
1736
}
1837

19-
if !info.IsDir() {
20-
// Read the file
21-
fileBytes, err := os.ReadFile(path)
38+
// If it's a symbolic link, resolve the target
39+
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
40+
target, err = os.Readlink(path)
41+
fmt.Printf("Resolved link from %s to %s\n", path, target)
2242
if err != nil {
23-
return fmt.Errorf("Failed to read file %s: %w", path, err)
43+
return err
2444
}
45+
}
2546

26-
// Compute the destination key (path) in the bucket
27-
relativePath, _ := filepath.Rel(sourcePath, path)
28-
destinationKey := filepath.Join(destPath, "input", relativePath)
47+
// If this is a subdirectory, make sure the path ends with a trailing slash before we create it
48+
// See https://pkg.go.dev/archive/zip#Writer.Create for details
49+
targetInfo, err := os.Stat(target)
50+
if err != nil {
51+
return err
52+
}
2953

30-
err = s3.PutObject(config, bucketName, destinationKey, fileBytes)
54+
if targetInfo.IsDir() {
55+
cleanPath := filepath.Clean(path) + string(filepath.Separator)
56+
fmt.Printf("Creating directory %s in the zipped archive\n", cleanPath)
57+
_, err = zipWriter.Create(cleanPath)
3158
if err != nil {
3259
return err
3360
}
61+
return nil
62+
}
63+
64+
// Don't recursively add this zipped archive
65+
if filepath.Base(path) == zipFileName {
66+
return nil
67+
}
68+
69+
fmt.Printf("Adding %s to the zipped archive\n", target)
3470

35-
fmt.Printf("Successfully uploaded %s to %s/%s\n", path, bucketName, destinationKey)
71+
// Create a new file entry in the zipped archive
72+
zipFileEntry, err := zipWriter.Create(path)
73+
if err != nil {
74+
return err
3675
}
76+
77+
// Open the file we're adding to the zipped archive
78+
file, err := os.Open(target)
79+
if err != nil {
80+
return err
81+
}
82+
83+
// Write this file to the zipped archive
84+
_, err = io.Copy(zipFileEntry, file)
85+
if err != nil {
86+
return err
87+
}
88+
89+
// Explicitly close the file once we're done to prevent a "too many open files" error
90+
err = file.Close()
91+
if err != nil {
92+
return err
93+
}
94+
3795
return nil
3896
})
97+
if err != nil {
98+
return err
99+
}
100+
fmt.Printf("Successfully added all files from %s to zipped archive at %s\n", sourcePath, zipFilePath)
101+
102+
// Make sure all prior writes are sync'd to the filesystem
103+
// This is necessary bc we're going to read the file right after writing it
104+
err = zipWriter.Flush()
105+
if err != nil {
106+
return err
107+
}
108+
err = zipFile.Sync()
109+
if err != nil {
110+
return err
111+
}
112+
113+
// Manually Closing is necessary to prevent zip file corruption during upload
114+
err = zipWriter.Close()
115+
if err != nil {
116+
return err
117+
}
118+
err = zipFile.Close()
119+
if err != nil {
120+
return err
121+
}
122+
123+
// Read the zipped archive
124+
fileBytes, err := os.ReadFile(zipFilePath)
125+
if err != nil {
126+
return fmt.Errorf("Failed to read zipped archive %s: %w", zipFilePath, err)
127+
}
128+
if len(fileBytes) == 0 {
129+
return fmt.Errorf("Failed to read zipped archive at %s: read zero bytes of data", zipFilePath)
130+
}
131+
132+
// Upload the zipped archive
133+
destKey := filepath.Join(destPath, "input.zip")
134+
fmt.Printf("Uploading archive (%v bytes) to %s\n", len(fileBytes), destKey)
135+
err = s3.PutObject(config, bucket, destKey, fileBytes)
136+
if err != nil {
137+
return err
138+
}
39139

140+
return nil
40141
}

cmd/cloudexec/user_data.sh.tmpl

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,13 @@ cleanup() {
126126
update_state "failed"
127127
fi
128128

129-
echo "Uploading results..."
130-
# shellcheck disable=SC2310
131-
s3cmd put -r ~/output/* "s3://${BUCKET_NAME}/job-${JOB_ID}/output/" || true # proceed to destroy droplet on error
132-
133-
echo "Uploading logs..."
134-
# shellcheck disable=SC2310
135-
s3cmd put /var/log/cloud-init-output.log "s3://${BUCKET_NAME}/job-${JOB_ID}/logs/" || true # proceed to destroy droplet on error
129+
output_files="$(ls -A ~/output/)"
130+
if [[ -n ${output_files} ]]; then
131+
echo "Uploading results..."
132+
s3cmd put -r ~/output/* "s3://${BUCKET_NAME}/job-${JOB_ID}/output/"
133+
else
134+
echo "Skipping results upload, no files found in ~/ouput"
135+
fi
136136

137137
if [[ -s ${stdout_log} ]]; then
138138
echo
@@ -150,6 +150,13 @@ cleanup() {
150150
echo "No error logs generated"
151151
fi
152152

153+
if [[ -s "/var/log/cloud-init-output.log" ]]; then
154+
echo "Uploading logs..."
155+
s3cmd put /var/log/cloud-init-output.log "s3://${BUCKET_NAME}/job-${JOB_ID}/logs/"
156+
else
157+
echo "No logs to upload.."
158+
fi
159+
153160
echo
154161
echo "Destroying droplet..."
155162
THIS_DROPLET_ID=$(curl -s http://169.254.169.254/metadata/v1/id)
@@ -195,11 +202,17 @@ echo "Running setup..."
195202
mkdir -p ~/output
196203
eval "${SETUP_COMMANDS}"
197204

198-
echo "Downloading inputs..."
199-
s3cmd get -r "s3://${BUCKET_NAME}/job-${JOB_ID}/input" ~/
205+
echo "Downloading input archive..."
206+
s3cmd get -r "s3://${BUCKET_NAME}/job-${JOB_ID}/input.zip" ~/
207+
if [[ ! -s ~/input.zip ]]; then
208+
echo "Error: Failed to download input archive"
209+
exit 1
210+
fi
200211

212+
echo "Unzipping input archive..."
213+
unzip ~/input.zip -d ~/
201214
if [[ ! -d ~/input ]]; then
202-
echo "Error: Failed to download inputs directory"
215+
echo "Error: Failed to unzip inputs directory"
203216
exit 1
204217
fi
205218

pkg/s3/s3.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ func PutObject(config config.Config, bucket string, key string, value []byte) er
159159
if err != nil {
160160
return fmt.Errorf("Failed to create %s directory in bucket %s: %w", key, bucket, err)
161161
}
162+
fmt.Printf("Successfully created directory in s3 bucket: %s/%s\n", bucket, key)
162163
return nil
163164
}
164165

@@ -179,8 +180,8 @@ func PutObject(config config.Config, bucket string, key string, value []byte) er
179180
if err != nil {
180181
return fmt.Errorf("Failed to upload file %s to bucket %s: %w", key, bucket, err)
181182
}
182-
// fmt.Printf("Successfully uploaded %s to %s\n", key, bucket)
183183

184+
fmt.Printf("Successfully uploaded file to s3 bucket: %s/%s\n", bucket, key)
184185
return nil
185186
}
186187

0 commit comments

Comments
 (0)