Skip to content
Permalink
Browse files
Add "get" command
The get command downloads tools from GitHub release pages
and from custom URLs using a go template to define the
URL and filename according to OS and architecture.

Tested with unit tests and with the two initial apps: faas-cli
and kubectl.

Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
  • Loading branch information
alexellis committed Jun 16, 2020
1 parent 0aef8d2 commit 4efd6d7869abd557e28d95e15da26eaf0ca31f35
Showing 8 changed files with 483 additions and 7 deletions.
@@ -5,4 +5,4 @@ kubeconfig
.idea/
mc
/arkade-*
/faas-cli-darwin
/faas-cli*
@@ -0,0 +1,111 @@
// Copyright (c) arkade author(s) 2020. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package cmd

import (
"fmt"
"io"
"net/http"
"os"
"path"
"strings"

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

func MakeGet() *cobra.Command {
tools := get.MakeTools()

var command = &cobra.Command{
Use: "get",
Short: "Get a release of a tool or application and install it on your local computer.",
Example: ` arkade get kubectl
arkade get openfaas`,
SilenceUsage: true,
}

command.RunE = func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
fmt.Println(arkadeGet)
return nil
}
var tool *get.Tool

if len(args) == 1 {
for _, t := range tools {
if t.Name == args[0] {
tool = &t
break
}
}
}
if tool == nil {
return fmt.Errorf("cannot get tool: %s", args[0])
}

fmt.Printf("Downloading %s\n", tool.Name)

arch, operatingSystem := env.GetClientArch()
version := ""

downloadURL, err := get.GetDownloadURL(tool, strings.ToLower(operatingSystem), strings.ToLower(arch), version)
if err != nil {
return err
}

fmt.Println(downloadURL)

res, err := http.DefaultClient.Get(downloadURL)
if err != nil {
return err
}

if res.Body != nil {
defer res.Body.Close()
}

if res.StatusCode != http.StatusOK {
return fmt.Errorf("incorrect status for downloading tool: %d", res.StatusCode)
}

_, fileName := path.Split(downloadURL)
tmp := os.TempDir()

outFilePath := path.Join(tmp, fileName)

out, err := os.Create(outFilePath)
if err != nil {
return err
}
defer out.Close()

if _, err = io.Copy(out, res.Body); err != nil {
return err
}

finalName := tool.Name
if strings.Contains(strings.ToLower(operatingSystem), "mingw") {
finalName = finalName + ".exe"
}

fmt.Printf(`Tool written to: %s
Run the following to copy to install the tool:
chmod +x %s
sudo install -m 755 %s /usr/local/bin/%s
`, outFilePath, outFilePath, outFilePath, finalName)

return err
}

return command
}

const arkadeGet = `Use "arkade get TOOL" to download a tool or application:
- kubectl
- faas-cli`
1 go.mod
@@ -7,5 +7,6 @@ require (
github.com/morikuni/aec v1.0.0
github.com/sethvargo/go-password v0.1.2
github.com/spf13/cobra v0.0.5
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
)
3 go.sum
@@ -29,6 +29,8 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
@@ -43,4 +45,5 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -15,7 +15,6 @@ func main() {
cmdVersion := cmd.MakeVersion()
cmdInstall := cmd.MakeInstall()
cmdInfo := cmd.MakeInfo()
cmdUpdate := cmd.MakeUpdate()

printarkadeASCIIArt := cmd.PrintArkadeASCIIArt

@@ -30,7 +29,8 @@ func main() {
rootCmd.AddCommand(cmdInstall)
rootCmd.AddCommand(cmdVersion)
rootCmd.AddCommand(cmdInfo)
rootCmd.AddCommand(cmdUpdate)
rootCmd.AddCommand(cmd.MakeUpdate())
rootCmd.AddCommand(cmd.MakeGet())

if err := rootCmd.Execute(); err != nil {
os.Exit(1)
@@ -13,24 +13,24 @@ import (
)

// GetClientArch returns a pair of arch and os
func GetClientArch() (string, string) {
func GetClientArch() (arch string, os string) {
task := execute.ExecTask{Command: "uname", Args: []string{"-m"}, StreamStdio: false}
res, err := task.Execute()
if err != nil {
log.Println(err)
}

arch := strings.TrimSpace(res.Stdout)
archResult := strings.TrimSpace(res.Stdout)

taskOS := execute.ExecTask{Command: "uname", Args: []string{"-s"}, StreamStdio: false}
resOS, errOS := taskOS.Execute()
if errOS != nil {
log.Println(errOS)
}

os := strings.TrimSpace(resOS.Stdout)
osResult := strings.TrimSpace(resOS.Stdout)

return arch, os
return archResult, osResult
}

func LocalBinary(name, subdir string) string {

0 comments on commit 4efd6d7

Please sign in to comment.