borrar implementación go
This commit is contained in:
parent
63690627d6
commit
165bf72672
4 changed files with 0 additions and 1373 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -1,12 +1,5 @@
|
|||
rootfs.ext4
|
||||
rootfs.qcow2
|
||||
fireactions
|
||||
*.ext4
|
||||
*.squashfs
|
||||
*.config.json
|
||||
vmlinux.bin
|
||||
node_modules/
|
||||
|
||||
*.log
|
||||
|
||||
build.cjs
|
||||
|
|
51
go.mod
51
go.mod
|
@ -1,51 +0,0 @@
|
|||
module gitea.nulo.in/Nulo/fireactions
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
|
||||
github.com/containerd/fifo v1.0.0 // indirect
|
||||
github.com/containernetworking/cni v1.0.1 // indirect
|
||||
github.com/containernetworking/plugins v1.0.1 // indirect
|
||||
github.com/firecracker-microvm/firecracker-go-sdk v1.0.0 // indirect
|
||||
github.com/go-openapi/analysis v0.21.2 // indirect
|
||||
github.com/go-openapi/errors v0.20.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||
github.com/go-openapi/loads v0.21.1 // indirect
|
||||
github.com/go-openapi/runtime v0.24.0 // indirect
|
||||
github.com/go-openapi/spec v0.20.4 // indirect
|
||||
github.com/go-openapi/strfmt v0.21.2 // indirect
|
||||
github.com/go-openapi/swag v0.21.1 // indirect
|
||||
github.com/go-openapi/validate v0.22.0 // indirect
|
||||
github.com/go-stack/stack v1.8.1 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/jaevor/go-nanoid v1.3.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/labstack/echo/v4 v4.10.2 // indirect
|
||||
github.com/labstack/gommon v0.4.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
|
||||
go.mongodb.org/mongo-driver v1.8.3 // indirect
|
||||
golang.org/x/crypto v0.6.0 // indirect
|
||||
golang.org/x/net v0.7.0 // indirect
|
||||
golang.org/x/sys v0.5.0 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
203
main.go
203
main.go
|
@ -1,203 +0,0 @@
|
|||
package main
|
||||
|
||||
// https://stanislas.blog/2021/08/firecracker/
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/firecracker-microvm/firecracker-go-sdk"
|
||||
"github.com/firecracker-microvm/firecracker-go-sdk/client/models"
|
||||
"github.com/jaevor/go-nanoid"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
)
|
||||
|
||||
func main() {
|
||||
e := echo.New()
|
||||
e.Use(middleware.Logger())
|
||||
e.Use(middleware.Recover())
|
||||
e.POST("/run", run)
|
||||
|
||||
e.Logger.Fatal(e.Start(":8080"))
|
||||
}
|
||||
|
||||
type runResp struct {
|
||||
VmId string
|
||||
}
|
||||
|
||||
func run(c echo.Context) error {
|
||||
script, err := ioutil.ReadAll(c.Request().Body)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
vmid, agent, m := startVM()
|
||||
err = agent.run(script)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
ctx := context.Background()
|
||||
if err := m.Wait(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
defer agent.off()
|
||||
|
||||
return c.JSON(http.StatusOK, runResp{
|
||||
VmId: vmid,
|
||||
})
|
||||
}
|
||||
|
||||
func startVM() (string, agentConfig, *firecracker.Machine) {
|
||||
nanid, err := nanoid.Standard(21)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
vmid := nanid()
|
||||
secret := nanid()
|
||||
socketPath := "/tmp/firecracker-" + vmid + ".sock"
|
||||
|
||||
cfg := firecracker.Config{
|
||||
SocketPath: socketPath,
|
||||
KernelImagePath: "vmlinux.bin",
|
||||
Drives: firecracker.NewDrivesBuilder("./rootfs.ext4").Build(),
|
||||
NetworkInterfaces: []firecracker.NetworkInterface{{
|
||||
CNIConfiguration: &firecracker.CNIConfiguration{
|
||||
NetworkName: "fcnet",
|
||||
IfName: "veth0-fire",
|
||||
BinPath: []string{"/opt/cni/bin", "/usr/libexec/cni"},
|
||||
},
|
||||
}},
|
||||
MachineCfg: models.MachineConfiguration{
|
||||
VcpuCount: firecracker.Int64(1),
|
||||
MemSizeMib: firecracker.Int64(1024),
|
||||
},
|
||||
// TODO: setup jailer
|
||||
KernelArgs: "console=ttyS0 reboot=k panic=1 pci=off fireactions.secret=" + secret,
|
||||
}
|
||||
|
||||
// TODO: change stdout/stderr files
|
||||
stdoutPath := "/tmp/stdout.log"
|
||||
stdout, err := os.OpenFile(stdoutPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to create stdout file: %v", err))
|
||||
}
|
||||
stderrPath := "/tmp/stderr.log"
|
||||
stderr, err := os.OpenFile(stderrPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to create stderr file: %v", err))
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
// build our custom command that contains our two files to
|
||||
// write to during process execution
|
||||
cmd := firecracker.VMCommandBuilder{}.
|
||||
WithBin("firecracker").
|
||||
WithSocketPath(socketPath).
|
||||
WithStdout(stdout).
|
||||
WithStderr(stderr).
|
||||
Build(ctx)
|
||||
|
||||
m, err := firecracker.NewMachine(ctx, cfg, firecracker.WithProcessRunner(cmd))
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to create new machine: %v", err))
|
||||
}
|
||||
|
||||
if err := m.Start(ctx); err != nil {
|
||||
panic(fmt.Errorf("failed to initialize machine: %v", err))
|
||||
}
|
||||
|
||||
ip := m.Cfg.NetworkInterfaces[0].StaticConfiguration.IPConfiguration.IPAddr.IP
|
||||
log.Printf("IP: %s", ip.String())
|
||||
|
||||
// defer m.StopVMM()
|
||||
|
||||
agent := agentConfig{ip: ip.String(), secret: secret}
|
||||
|
||||
if err := agent.waitForAgent(); err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
ctx := context.Background()
|
||||
if err := m.Wait(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
os.Remove(cfg.SocketPath)
|
||||
}()
|
||||
// if err := m.Wait(ctx); err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
|
||||
return vmid, agent, m
|
||||
}
|
||||
|
||||
type agentConfig struct {
|
||||
ip string
|
||||
secret string
|
||||
}
|
||||
|
||||
func (a agentConfig) request() *http.Request {
|
||||
req, err := http.NewRequest("GET", "http://"+a.ip+":8080/hello", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+a.secret)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return req
|
||||
}
|
||||
|
||||
func (a agentConfig) run(script []byte) error {
|
||||
req, err := http.NewRequest("POST", "http://"+a.ip+":8080/run", bytes.NewBuffer(script))
|
||||
req.Header.Set("Authorization", "Bearer "+a.secret)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
byt, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Println("[QIOdLqxLoKIMQ0uGoxNuu]", string(byt))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a agentConfig) off() error {
|
||||
return a.run([]byte("#!/bin/sh\nreboot"))
|
||||
}
|
||||
|
||||
func (a agentConfig) waitForAgent() error {
|
||||
client := http.Client{
|
||||
Timeout: time.Millisecond * 50,
|
||||
}
|
||||
for {
|
||||
log.Println("waiting for agent to come up...")
|
||||
req := a.request()
|
||||
req.Method = "GET"
|
||||
req.URL.Path = "/hello"
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
time.Sleep(time.Millisecond * 200)
|
||||
continue
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
log.Println("Agent is failing", resp)
|
||||
return errors.New("Agent is failing")
|
||||
}
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
Loading…
Reference in a new issue