I am creating a wrapper for firecracker.
To start a VM with firecracker on command line, you have to pass a socket file to the firecracker
executable. Something like this:
firecracker --api-sock /path/to/file.socket
Then from another terminal, you can make requests to this server/socket something like this:
curl --unix-socket /tmp/firecracker.socket -XPUT 'http://localhost/actions' -d '{"action_type": "SendCtrlAltDel"}'
I am trying to replicate the same thing from within a Gin server.
I have an endpoint which does the first work, which is to start a server. A minimal code looks like this:
cmd := exec.Command("firecracker", "--api-sock", "/path/to/file.socket")
err := cmd.Start()
This endpoint starts the server and listens for any command. The problem is, I don't know how to use the socket file to make a PUT request to this server. I have found this on the web, but it does not makes much sense to me.
Here is a starter code which does not use any socket file.
func BootSource(c *gin.Context) {
var body models.BootSource
c.BindJSON(&body)
bodyJson, _ := json.Marshal(body)
// initialize http client
client := &http.Client{}
// set the HTTP method, url, and request body
req, err := http.NewRequest(http.MethodPut, "http://localhost/boot-source", bytes.NewBuffer(bodyJson))
if err != nil {
panic(err)
}
// set the request header Content-Type for json
_, err = client.Do(req)
if err != nil {
panic(err)
}
}
How do I make this PUT request use the socket file?
Please also note that I'm using Gin framework.
To do this, you'll need to override the Transport used by your http.Client
to configure a function for it to use to create a connection to the socket:
client := http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
return net.Dial("unix", "/path/to/socket")
},
},
}
You can then use that client, and all requests made by it will use that connection. Usually for HTTP services exposed over a socket, the host used in the request is not important, so you can just use any value that makes sense to you e.g
client.Get("http://firecracker/some/api/path")
However, as you are trying to use the Firecracker API, why not just use their SDK: https://github.com/firecracker-microvm/firecracker-go-sdk
This will handle the set up of the connection for you, and prevent you needing to manually craft all of the requests.