Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add firecracker install #667

Merged
merged 1 commit into from
Apr 6, 2022
Merged
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
119 changes: 119 additions & 0 deletions cmd/system/firecracker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright (c) arkade author(s) 2022. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package system

import (
"fmt"
"os"
"strings"

"github.com/alexellis/arkade/pkg/archive"
"github.com/alexellis/arkade/pkg/env"
"github.com/alexellis/arkade/pkg/get"
"github.com/spf13/cobra"
)

const (
githubDownloadTemplate = "https://github.com/%s/%s/releases/download/%s/%s"
githubLatest = "latest"

firecrackerOwner = "firecracker-microvm"
firecrackerRepo = "firecracker"

repoFlagName = "repo"
versionFlagName = "version"
pathFlagName = "path"
progressFlagName = "progress"
)

func MakeInstallFirecracker() *cobra.Command {

command := &cobra.Command{
Use: "firecracker",
Short: "Install Firecracker",
Long: `Install Firecracker and its Jailer.`,
Example: ` arkade system install firecracker
arkade system install firecracker --version v1.0.0`,
SilenceUsage: true,
}

command.Flags().StringP(versionFlagName, "v", githubLatest, "The version for Firecracker to install")
command.Flags().StringP(pathFlagName, "p", "/usr/local/bin", "Installation path, where a go subfolder will be created")
command.Flags().Bool(progressFlagName, true, "Show download progress")

command.RunE = func(cmd *cobra.Command, args []string) error {
installPath, _ := cmd.Flags().GetString(pathFlagName)
version, _ := cmd.Flags().GetString(versionFlagName)
progress, _ := cmd.Flags().GetBool(progressFlagName)

fmt.Printf("Installing Firecracker to %s\n", installPath)

if err := os.MkdirAll(installPath, 0755); err != nil && !os.IsExist(err) {
fmt.Printf("Error creating directory %s, error: %s\n", installPath, err.Error())
}

arch, osVer := env.GetClientArch()

if strings.ToLower(osVer) != "linux" {
return fmt.Errorf("this app only supports Linux")
}

if arch != "x86_64" && arch != "aarch64" {
return fmt.Errorf("this app only supports x86_64 and aarch64 and not %s", arch)
}

if version == githubLatest {
v, err := get.FindGitHubRelease(firecrackerOwner, firecrackerRepo)
if err != nil {
return err
}

version = v
} else if !strings.HasPrefix(version, "v") {
version = "v" + version
}

fmt.Printf("Installing version: %s for: %s\n", version, arch)

filename := fmt.Sprintf("firecracker-%s-%s.tgz", version, arch)
dlURL := fmt.Sprintf(githubDownloadTemplate, firecrackerOwner, firecrackerRepo, version, filename)

fmt.Printf("Downloading from: %s\n", dlURL)
outPath, err := get.DownloadFileP(dlURL, progress)
if err != nil {
return err
}
fmt.Printf("Downloaded to: %s\n", outPath)

f, err := os.OpenFile(outPath, os.O_RDONLY, 0644)
if err != nil {
return err
}
defer f.Close()

tempUnpackPath, err := os.MkdirTemp(os.TempDir(), "firecracker*")
Copy link
Owner

@alexellis alexellis Apr 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we benefit from a defer os.Remove/Dir(tempUnpackPath)?

Copy link
Sponsor Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes i think you are right.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps you could do that in the next app you contribute? @Shikachuu is covering containerd but the rest are fair game.

Node should be fairly similar to add?

https://nodejs.org/en/download/

if err != nil {
return err
}
fmt.Printf("Unpacking Firecracker to: %s\n", tempUnpackPath)
if err := archive.Untar(f, tempUnpackPath, true); err != nil {
return err
}

fmt.Printf("Copying Firecracker binaries to: %s\n", installPath)
filesToCopy := map[string]string{
fmt.Sprintf("%s/firecracker-%s-%s", tempUnpackPath, version, arch): fmt.Sprintf("%s/firecracker", installPath),
fmt.Sprintf("%s/jailer-%s-%s", tempUnpackPath, version, arch): fmt.Sprintf("%s/jailer", installPath),
}
for src, dst := range filesToCopy {
if _, copyErr := get.CopyFile(src, dst); copyErr != nil {
return err
}
}

return nil
}

return command
}
1 change: 1 addition & 0 deletions cmd/system/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func MakeInstall() *cobra.Command {
}

command.AddCommand(MakeInstallGo())
command.AddCommand(MakeInstallFirecracker())

return command
}
4 changes: 2 additions & 2 deletions pkg/get/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func Download(tool *Tool, arch, operatingSystem, version string, downloadMode in
if !quiet {
log.Printf("Copying %s to %s\n", outFilePath, localPath)
}
_, err = copyFile(outFilePath, localPath)
_, err = CopyFile(outFilePath, localPath)
if err != nil {
return "", "", err
}
Expand Down Expand Up @@ -123,7 +123,7 @@ func downloadFile(downloadURL string, displayProgress bool) (string, error) {
return outFilePath, nil
}

func copyFile(src, dst string) (int64, error) {
func CopyFile(src, dst string) (int64, error) {
sourceFileStat, err := os.Stat(src)
if err != nil {
return 0, err
Expand Down
4 changes: 2 additions & 2 deletions pkg/get/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func (tool Tool) GetURL(os, arch, version string, quiet bool) (string, error) {
log.Printf("Looking up version for %s", tool.Name)
}

v, err := findGitHubRelease(tool.Owner, tool.Repo)
v, err := FindGitHubRelease(tool.Owner, tool.Repo)
if err != nil {
return "", err
}
Expand Down Expand Up @@ -175,7 +175,7 @@ func getURLByGithubTemplate(tool Tool, os, arch, version string) (string, error)
return getBinaryURL(tool.Owner, tool.Repo, version, downloadName), nil
}

func findGitHubRelease(owner, repo string) (string, error) {
func FindGitHubRelease(owner, repo string) (string, error) {
url := fmt.Sprintf("https://github.com/%s/%s/releases/latest", owner, repo)

timeout := time.Second * 5
Expand Down