Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ _book

# Built images
*.img
*.tar
42 changes: 32 additions & 10 deletions cmd/eli/buildNodeCommand.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"fmt"
"io"
"log"
"os"

"github.com/ernoaapa/eliot/pkg/cmd"
Expand All @@ -18,7 +19,7 @@ var buildNodeCommand = cli.Command{
Usage: "Build node image",
UsageText: `eli build node [options] [FILE | URL]

# Build default node image
# Build default node disk img -file
eli build node

# Create Linuxkit file but don't build it
Expand All @@ -27,7 +28,7 @@ var buildNodeCommand = cli.Command{

# Build from custom config and unpack to directory
mkdir dist
eli build node custom-linuxkit.yml | tar xv -C dist
eli build node custom-linuxkit.yml --format tar | tar xv -C dist
`,
Flags: []cli.Flag{
cli.BoolFlag{
Expand All @@ -42,22 +43,27 @@ var buildNodeCommand = cli.Command{
},
cli.StringFlag{
Name: "output",
Usage: "Target output file",
Value: "image.tar",
Usage: "Target output file. (default: eliot-os.tar or eliot-os.img)",
},
cli.StringFlag{
Name: "type",
Usage: "Target build type, one of Linuxkit output types",
Value: "rpi3",
},
cli.StringFlag{
Name: "format",
Usage: "Target output format. One of [tar, img] (default: img)",
Value: "img",
},
},
Action: func(clicontext *cli.Context) (err error) {
var (
source = clicontext.Args().First()
dryRun = clicontext.Bool("dry-run")
serverURL = clicontext.String("build-server")
outputFile = clicontext.String("output")
outputType = clicontext.String("type")
source = clicontext.Args().First()
dryRun = clicontext.Bool("dry-run")
serverURL = clicontext.String("build-server")
outputType = clicontext.String("type")
outputFormat = clicontext.String("format")
outputFile = getBuildOutputFile(outputFormat, clicontext.String("output"))

uiline ui.Line
linuxkit []byte
Expand Down Expand Up @@ -93,7 +99,7 @@ var buildNodeCommand = cli.Command{
}

uiline = ui.NewLine().Loadingf("Building Linuxkit image in remote build server...")
image, err := build.BuildImage(serverURL, outputType, linuxkit)
image, err := build.BuildImage(serverURL, outputType, outputFormat, linuxkit)
if err != nil {
uiline.Errorf("Failed to build Linuxkit image: %s", err)
return errors.Wrap(err, "Failed to build Linuxkit image")
Expand All @@ -110,3 +116,19 @@ var buildNodeCommand = cli.Command{
return nil
},
}

func getBuildOutputFile(format, outputFile string) string {
if outputFile != "" {
return outputFile
}

switch format {
case "img":
return "eliot-os.img"
case "tar":
return "eliot-os.tar"
default:
log.Fatalf("Unknown output format %s, cannot resolve default output file", format)
return ""
}
}
2 changes: 1 addition & 1 deletion docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* [eli delete pod](client.md#eli-delete-pod-pod-name)
* [eli exec](client.md#eli-exec---container-id-pod-name----command)
* [eli attach](client.md#eli-attach--i---container-id-pod-name)
* [eli build device](client.md#eli-build-device)
* [eli build device](client.md#eli-build-device---format-img--tar)
* [Configuration](configuration.md)
* [Pod Specification](configuration.md#pod-specification)
* [Project Configuration](configuration.md#project-configuration)
Expand Down
14 changes: 7 additions & 7 deletions docs/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,16 +280,16 @@ Hello world!

You can also give `-i` flag to hook up your stdin into the container, but watch out, if you for example press ^C (ctrl+c) to exit, you actually send kill signal to the process in the container which will stop the container.

## `eli build device`
## `eli build device [--format img | tar]`
Easiest way to run Eliot in your device is to use [EliotOS](https://github.com/ernoaapa/eliot-os) which is minimal Operating System where's just minimal components installed to run Eliot and everything else run on top of the Eliot in containers.

With `eli build device` command you can build EliotOS image that you can just unpack to your device sdcard.
With `eli build device` command you can build EliotOS image that you can just write to your device sdcard.

> Note: At the moment we support only RaspberryPi 3b, for other devices [see installation guide](installation.md)

```shell
**[terminal]
**[prompt ernoaapa@mac]**[path ~]**[delimiter $ ]**[command eli build device > my-image.tar]
**[prompt ernoaapa@mac]**[path ~]**[delimiter $ ]**[command eli build device > my-image.img]
```

[EliotOS](https://github.com/ernoaapa/eliot-os) is built with [Linuxkit]([EliotOS](https://github.com/ernoaapa/eliot-os) and you can view the Linuxkit configuration with `--dry-run` flag.
Expand All @@ -298,7 +298,7 @@ With `eli build device` command you can build EliotOS image that you can just un
**[terminal]
**[prompt ernoaapa@mac]**[path ~]**[delimiter $ ]**[command eli build device --dry-run]
✓ Resolved Linuxkit config!
✓ Resolved output: image.tar!
✓ Resolved output: image.img!
kernel:
image: linuxkit/kernel:4.9.72
cmdline: "console=tty0 console=ttyS0 console=ttyAMA0"
Expand Down Expand Up @@ -374,7 +374,7 @@ If you want to customise the Linuxkit configuration before building
**[terminal]
**[prompt ernoaapa@mac]**[path ~]**[delimiter $ ]**[command eli build device --dry-run > custom-linuxkit.yml]
# Edit the my-custom-linuxkit.yml -file...
**[prompt ernoaapa@mac]**[path ~]**[delimiter $ ]**[command eli build device custom-linuxkit.yml > custom-image.tar]
**[prompt ernoaapa@mac]**[path ~]**[delimiter $ ]**[command eli build device custom-linuxkit.yml > custom-image.img]
```

#### Shell piping
Expand All @@ -400,7 +400,7 @@ files:
```shell
**[terminal]
**[prompt ernoaapa@mac]**[path ~]**[delimiter $ ]**[command sed -e "s/\MY-HOSTNAME/eliot-$(date +%s)/" custom-linuxkit.yml \
| eli build device \
| eli build device --format tar \
| tar xv -C /Volumes/raspberrypi3]
```

Expand All @@ -410,6 +410,6 @@ _Pretty handy, ain't it? :D_

#### How it works?
Linuxkit doesn't support building arm images on x86, but RaspberryPi is arm based computer.
For building images, Eliot hosts [Linuxkit build server](https://github.com/ernoaapa/linuxkit-server) and when you execute `eli build device`, it sends the config to `build.eliot.run` server, which builds the image on arm server and send it back as tar package.
For building images, Eliot hosts [Linuxkit build server](https://github.com/ernoaapa/linuxkit-server) and when you execute `eli build device`, it sends the config to `build.eliot.run` server, which builds the image on arm server and send it back as either disk image (.img) or tar package (.tar).

If you want to host and use your own build server, see the [Linuxkit build server documentation](https://github.com/ernoaapa/linuxkit-server) and pass `--build-server http://my-custom-build-server.com` flag to build the image in your own server.
36 changes: 29 additions & 7 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,37 @@ There's three options for device installation
### EliotOS on RaspberryPI3
By far the easiest and most secure way to use Eliot is by using [EliotOS](eliotos.md). EliotOS is minimal Linux Operating System, built with [linuxkit](https://github.com/linuxkit/linuxkit), which contains only minimal components to run Eliot which are Linux kernel, `runc`, `containerd` and `eliotd` daemon. Check the [EliotOS](eliotos.md) section for more info.

`eli` provides [build command](client.md#eli-build-device) to build [EliotOS](eliotos.md) for RaspberryPI3 and install it to the sdcard.
`eli` provides [build command](client.md#eli-build-device) to build [EliotOS](eliotos.md) for RaspberryPI3 and install it to the sdcard. There's few different ways to do it, depending on your preferences.

1. Format sdcard as you would normally
2. Mount it to for example `/Volumes/rpi3`
3. Build image and unpack it to the directory `eli build device | tar xv -C /Volumes/rpi3`
#### a) Write image with Etcher
[Etcher](https://etcher.io/) is really handy desktop app for Win, Mac and Linux for writing img -files to sdcards.
1. Install [Etcher](https://etcher.io/)
2. Build image file `eli build device`
3. Start Etcher and select created `eliot-os.img` as the source and your sdcard drive as target

### b) Write iamge with `dd`
If you're for example writing the image in headless server and you don't want to use any gui, you can write the image with `dd`

**WARNING! With dd tool can overwrite any partition of your machine, for example your primary OS partition! Use only if you know what you do.**

1. Connect your sdcard and resolve what device is the card (in this example it's `disk3`)
2. Unmount the disk (but keep connected)
3. Build img-file `eli build device`
4. Write to card `sudo dd bs=1m if=eliot-os.img of=/dev/rdisk3 conv=sync`

#### c) Write disk manually
You can also build the disk manually, if none of above suite to you.

1. Format sdcard as FAT32 and name it for example `rpi3`
2. Mount it to for example `/Volumes/rpi3` (Mac does this automatically)
3. Build image and unpack it to the sdcard `eli build device --format tar | tar xv -C /Volumes/rpi3`
4. Unmount the disk
5. Connect RaspberryPI with ethernet cable to same network with your laptop and power on!
6. In less than 10s you should see the device with command `eli get devices`
7. And that's it! ☺

#### Boot up!
Now just connect RaspberryPI with ethernet cable to same network with your laptop and power on!
In less than 10s you should see the device with command `eli get devices`.

And that's it! ☺

Next step is to follow [getting started guide](getting_started.md#deploy-first-app) and deploy first app!

Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/build/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ func ResolveLinuxkitConfig(source string) (linuxkit []byte, err error) {

// BuildImage builds given Linuxkit config and returns the image as io.ReadClose or error
// Note: you must call image.Close()
func BuildImage(serverURL, outputType string, config []byte) (io.ReadCloser, error) {
res, err := http.Post(fmt.Sprintf("%s/linuxkit/%s/build/%s", serverURL, "eli-cli", outputType), "application/yml", bytes.NewReader(config))
func BuildImage(serverURL, outputType, outputFormat string, config []byte) (io.ReadCloser, error) {
res, err := http.Post(fmt.Sprintf("%s/linuxkit/%s/build/%s?output=%s", serverURL, "eli-cli", outputType, outputFormat), "application/yml", bytes.NewReader(config))
if err != nil {
return nil, errors.Wrap(err, "Error while making request to Linuxkit build server")
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/build/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func TestBuildImage(t *testing.T) {
}))
defer ts.Close()

image, err := BuildImage(ts.URL, "rpi3", exampleLinuxkitConfig)
image, err := BuildImage(ts.URL, "rpi3", "img", exampleLinuxkitConfig)
assert.NoError(t, err)

tar, err := ioutil.ReadAll(image)
Expand All @@ -73,6 +73,6 @@ func TestBuildImageReturnErrorMessage(t *testing.T) {
}))
defer ts.Close()

_, err := BuildImage(ts.URL, "rpi3", exampleLinuxkitConfig)
_, err := BuildImage(ts.URL, "rpi3", "tar", exampleLinuxkitConfig)
assert.True(t, strings.Contains(err.Error(), "This is the error"))
}