diff --git a/Makefile b/Makefile index c08a877..57f497c 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,9 @@ build: go build -a -o bin/helmenv cmd/helmenv/main.go; \ go build -a -o bin/helm-wrapper cmd/helm-wrapper/main.go; \ go build -a -o bin/kbenv cmd/kbenv/main.go; \ - go build -a -o bin/kubectl-wrapper cmd/kubectl-wrapper/main.go; + go build -a -o bin/kubectl-wrapper cmd/kubectl-wrapper/main.go; \ + go build -a -o bin/ocenv cmd/ocenv/main.go; \ + go build -a -o bin/oc-wrapper cmd/oc-wrapper/main.go; clean: -rm -r bin/ @@ -43,7 +45,7 @@ int-test: | $(KIND) bats tests/managers.test bats tests/wrappers.test -PLATFORMS := linux-amd64 linux-386 darwin-amd64 darwin-386 windows-amd64 windows-386 +PLATFORMS := linux-amd64 linux-386 darwin-amd64 windows-amd64 windows-386 temp = $(subst -, ,$@) os = $(word 1, $(temp)) arch = $(word 2, $(temp)) @@ -54,5 +56,8 @@ $(PLATFORMS): CGO_ENABLED=0 GOOS=$(os) GOARCH=$(arch) go build -a -o bin/helm-wrapper-$(os)-$(arch) cmd/helm-wrapper/main.go; \ CGO_ENABLED=0 GOOS=$(os) GOARCH=$(arch) go build -a -o bin/kbenv-$(os)-$(arch) cmd/kbenv/main.go; \ CGO_ENABLED=0 GOOS=$(os) GOARCH=$(arch) go build -a -o bin/kubectl-wrapper-$(os)-$(arch) cmd/kubectl-wrapper/main.go; \ + CGO_ENABLED=0 GOOS=$(os) GOARCH=$(arch) go build -a -o bin/ocenv-$(os)-$(arch) cmd/ocenv/main.go; \ + CGO_ENABLED=0 GOOS=$(os) GOARCH=$(arch) go build -a -o bin/oc-wrapper-$(os)-$(arch) cmd/oc-wrapper/main.go; \ tar -C bin -cvzf releases/helmenv-$(os)-$(arch).tar.gz helmenv-$(os)-$(arch) helm-wrapper-$(os)-$(arch); \ - tar -C bin -cvzf releases/kbenv-$(os)-$(arch).tar.gz kbenv-$(os)-$(arch) kubectl-wrapper-$(os)-$(arch); + tar -C bin -cvzf releases/kbenv-$(os)-$(arch).tar.gz kbenv-$(os)-$(arch) kubectl-wrapper-$(os)-$(arch); \ + tar -C bin -cvzf releases/ocenv-$(os)-$(arch).tar.gz ocenv-$(os)-$(arch) oc-wrapper-$(os)-$(arch); diff --git a/cmd/oc-wrapper/README.md b/cmd/oc-wrapper/README.md new file mode 100644 index 0000000..a8df029 --- /dev/null +++ b/cmd/oc-wrapper/README.md @@ -0,0 +1,5 @@ +# OC Wrapper + +This is a OC wrapper. It doesn't do much more than execute every command as +is. The only special thing it does is to choose which version to use. Just use +it as a substitute of the binary. Please refer to [ocenv](../ocenv/README.md). diff --git a/cmd/oc-wrapper/main.go b/cmd/oc-wrapper/main.go new file mode 100644 index 0000000..6a068cc --- /dev/null +++ b/cmd/oc-wrapper/main.go @@ -0,0 +1,11 @@ +package main + +import ( + "github.com/little-angry-clouds/kubernetes-binaries-managers/internal/wrapper" +) + +func main() { + var binName string = "oc" + + wrapper.Wrapper(binName) +} diff --git a/cmd/ocenv/README.md b/cmd/ocenv/README.md new file mode 100644 index 0000000..a235f46 --- /dev/null +++ b/cmd/ocenv/README.md @@ -0,0 +1,165 @@ +![Static Tests](https://github.com/little-angry-clouds/kubernetes-binaries-managers/workflows/Generic%20tests/badge.svg) ![Int Test Linux](https://github.com/little-angry-clouds/kubernetes-binaries-managers/workflows/Int%20Test%20Linux/badge.svg) ![Int Test MacOS](https://github.com/little-angry-clouds/kubernetes-binaries-managers/workflows/Int%20Test%20MacOS/badge.svg) ![Int Test Windows](https://github.com/little-angry-clouds/kubernetes-binaries-managers/workflows/Int%20Test%20Windows/badge.svg) + +# ocenv + +[OC](https://docs.openshift.com/container-platform/4.2/cli_reference/openshift_cli/getting-started-cli.html) version +manager inspired by [tfenv](https://github.com/tfutils/tfenv/). + +## Features + +- Install OC versions in a reproducible and easy way +- Enforce version in your git repositories with a `.oc_version` file + +## Supported OS + +Currently ocenv supports the following OSes + +- Mac OS +- Linux +- Windows + +## Installation + +There are two components in `ocenv`. One is the `ocenv` binary, the other one +is a `oc` wrapper. It works as if were `oc`, but it has some logic to choose +the version to execute. You should take care and ensure that you don't have any +`oc` binary in your path. To check which binary you're executing, you can see +it with: + +```bash +$ which oc +/opt/brew/bin/oc +``` + +### Homebrew + +This is the recomended way, since it provides upgrades. It should work in Mac, +Linux and Windows with WSL. + +```bash +# Just the first time, activate the repository +brew tap little-angry-clouds/homebrew-my-brews +# To install +brew install ocenv +# To upgrade +brew upgrade ocenv +``` + +You should add your `homebrew` binary path to your PATH: + +```bash +echo 'export PATH="$(brew --prefix)/bin/:$PATH"' >> ~/.bashrc +# Or +echo 'export PATH="$(brew --prefix)/bin/:$PATH"' >> ~/.zshrc +``` + +For Windows you should do the weird stuff that it needs to set an environmental variable. + +### Manually + +1. Add `~/.bin` to your `$PATH` and create it if doesn't exist + +```bash +echo 'export PATH="$HOME/.bin:$PATH"' >> ~/.bashrc +# Or +echo 'export PATH="$HOME/.bin:$PATH"' >> ~/.zshrc + +mkdir -p ~/.bin +``` + +2. Download the binaries and put them on your path + +Go to [the releases +page](https://github.com/little-angry-clouds/kubernetes-binaries-managers/releases) +and download the version you want. For example: + +```bash +wget https://github.com/little-angry-clouds/kubernetes-binaries-managers/releases/download/0.0.4/ocenv-linux-amd64.tar.gz +tar xzf ocenv-linux-amd64.tar.gz +mv ocenv-linux-amd64 ~/.bin/ocenv +mv oc-wrapper-linux-amd64 ~/.bin/oc +``` + +And that's it! + +## Usage + +### Help + +```bash +$ ocenv help +Oc version manager + +Usage: + ocenv [command] + +Available Commands: + help Help about any command + install Install binary + list Lists local and remote versions + uninstall Uninstall binary + use Set the default version to use + +Flags: + -h, --help help + +Use "ocenv [command] --help" for more information about a command. +``` + +### List installable versions + +This option uses Github API to paginate all versions. Github API has some usage +limitations. It usually works, but if you happen to do a lot of requests to +github or are on an office or similar, chances are that this command will fail. +You can still install binaries if you know the version you want, thought. + +```bash +$ ocenv list remote +4.7.0-0.okd-2021-07-03-190901 +4.7.0-0.okd-2021-06-19-191547 +4.7.0-0.okd-2021-06-13-090745 +4.7.0-0.okd-2021-06-04-191031 +4.7.0-0.okd-2021-05-22-050008 +4.7.0-0.okd-2021-04-24-103438 +4.7.0-0.okd-2021-04-11-124433 +... +``` + +### List installed versions + +```bash +$ ocenv list local +4.7.0-0.okd-2021-07-03-190901 +4.7.0-0.okd-2021-06-19-191547 +4.7.0-0.okd-2021-06-13-090745 +4.7.0-0.okd-2021-06-04-191031 +4.7.0-0.okd-2021-05-22-050008 +4.7.0-0.okd-2021-04-24-103438 +4.7.0-0.okd-2021-04-11-124433 +``` + +### Install version + +```bash +$ ocenv install 4.7.0-0.okd-2021-07-03-190901 +Downloading binary... +Done! Saving it at /home/user/.bin/oc-4.7.0-0.okd-2021-07-03-190901 +``` + +### Use version + +```bash +$ ocenv use 4.7.0-0.okd-2021-07-03-190901 +Done! Using 4.7.0-0.okd-2021-07-03-190901 version. +``` + +### Uninstall version + +```bash +$ ocenv uninstall 4.7.0-0.okd-2021-07-03-190901 +Done! 4.7.0-0.okd-2021-07-03-190901 version uninstalled from /home/ap/.bin/oc-4.7.0-0.okd-2021-07-03-190901. +``` + +## License + +GPL3 diff --git a/cmd/ocenv/main.go b/cmd/ocenv/main.go new file mode 100644 index 0000000..dc588ff --- /dev/null +++ b/cmd/ocenv/main.go @@ -0,0 +1,22 @@ +package main + +import ( + "os" + + "github.com/little-angry-clouds/kubernetes-binaries-managers/internal/cmd" + "github.com/mitchellh/go-homedir" +) + +var binaryDownloadURL string = "https://github.com/openshift/okd/releases/download/%s/openshift-client-%s-%s.tar.gz" // nolint:lll +var versionsAPI string = "https://api.github.com/repos/openshift/okd/releases?per_page=100&page=" // nolint:lll + +func main() { + home, _ := homedir.Dir() + _ = os.MkdirAll(home+"/.bin", os.ModePerm) + cmd.BinaryDownloadURL = binaryDownloadURL + cmd.VersionsAPI = versionsAPI + cmd.BinaryToInstall = "oc" + cmd.RootCmd.Use = "ocenv" + cmd.RootCmd.Short = "OC version manager" + cmd.Execute() +} diff --git a/go.mod b/go.mod index 76ef785..8c52e6a 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,8 @@ require ( github.com/fogleman/gg v1.3.0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/hashicorp/go-version v1.2.1 - github.com/jpoles1/gopherbadger v2.3.0+incompatible // indirect - github.com/mholt/archiver/v3 v3.3.0 + github.com/jpoles1/gopherbadger v2.4.0+incompatible // indirect + github.com/mholt/archiver/v3 v3.5.1-0.20210618180617-81fac4ba96e4 github.com/mitchellh/go-homedir v1.1.0 github.com/spf13/cobra v1.0.0 github.com/stretchr/testify v1.4.0 diff --git a/go.sum b/go.sum index ac03b32..8616fba 100644 --- a/go.sum +++ b/go.sum @@ -17,6 +17,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andybalholm/brotli v0.0.0-20190621154722-5f990b63d2d6 h1:bZ28Hqta7TFAK3Q08CMvv8y3/8ATaEqv2nGoc6yff6c= github.com/andybalholm/brotli v0.0.0-20190621154722-5f990b63d2d6/go.mod h1:+lx6/Aqd1kLJ1GQfkvOnaZ1WGmLpMpbprPuIOOZX30U= +github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc= +github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -37,6 +39,8 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8 github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= +github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= +github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -78,11 +82,14 @@ github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= +github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -114,6 +121,8 @@ github.com/jpoles1/gopherbadger v2.2.0+incompatible h1:2aysGaPeOKyAMvpDRy8MwQoOy github.com/jpoles1/gopherbadger v2.2.0+incompatible/go.mod h1:DVwxsf5adYLiDOj955t/ejfCRWjKA5tme6Vejb72Ro0= github.com/jpoles1/gopherbadger v2.3.0+incompatible h1:XMBrJ4UAGZkHisRncvL0xaNB5U8rbqqtzfVXKyLcn7s= github.com/jpoles1/gopherbadger v2.3.0+incompatible/go.mod h1:DVwxsf5adYLiDOj955t/ejfCRWjKA5tme6Vejb72Ro0= +github.com/jpoles1/gopherbadger v2.4.0+incompatible h1:UHNcdQnmeUo8kAIAZfz55Dkev3zM/Jj2SMgeEwkMO8A= +github.com/jpoles1/gopherbadger v2.4.0+incompatible/go.mod h1:DVwxsf5adYLiDOj955t/ejfCRWjKA5tme6Vejb72Ro0= github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -125,9 +134,13 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.2 h1:LfVyl+ZlLlLDeQ/d2AqfGIIH4qEDu0Ed2S5GyhCWIWY= github.com/klauspost/compress v1.9.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.11.4 h1:kz40R/YWls3iqT9zX9AHN3WoVsrAWVyui5sxuLqiXqU= +github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/pgzip v1.2.1 h1:oIPZROsWuPHpOdMVWLuJZXwgjhrW8r1yEX8UqMyeNHM= github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= @@ -145,6 +158,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mholt/archiver/v3 v3.3.0 h1:vWjhY8SQp5yzM9P6OJ/eZEkmi3UAbRrxCq48MxjAzig= github.com/mholt/archiver/v3 v3.3.0/go.mod h1:YnQtqsp+94Rwd0D/rk5cnLrxusUBUXg+08Ebtr1Mqao= +github.com/mholt/archiver/v3 v3.5.1-0.20210618180617-81fac4ba96e4 h1:S7ICJmgiEB5WbKXg3CPL/qmJKxxKf33yJSkxqbdiTQA= +github.com/mholt/archiver/v3 v3.5.1-0.20210618180617-81fac4ba96e4/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -160,6 +175,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nwaples/rardecode v1.0.0 h1:r7vGuS5akxOnR4JQSkko62RJ1ReCMXxQRPtxsiFMBOs= github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ= +github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -170,6 +187,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM= +github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -214,6 +233,9 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8= github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I= +github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -290,6 +312,7 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= diff --git a/internal/binary/binary.go b/internal/binary/binary.go index 9bfa59a..a2be834 100644 --- a/internal/binary/binary.go +++ b/internal/binary/binary.go @@ -16,6 +16,12 @@ import ( "github.com/mholt/archiver/v3" ) +const ( + zip = ".zip" + targz = ".tar.gz" + exe = ".exe" +) + type DownloadBinaryError struct { Err string URL string @@ -33,7 +39,7 @@ func (e *DownloadBinaryError) Error() string { return error } -func DownloadBinary(version string, url string) ([]byte, error) { +func DownloadBinary(version string, url string) ([]byte, error) { // nolint: funlen var osArch string var err error var body []byte @@ -44,17 +50,29 @@ func DownloadBinary(version string, url string) ([]byte, error) { osArch, _ = GetOSArch() os := strings.Split(osArch, "/")[0] arch := strings.Split(osArch, "/")[1] - url = fmt.Sprintf(url, version, os, arch) + + if strings.Contains(url, "openshift") { + // They use mac instead of darwin in the url + if os == "darwin" { + os = "mac" + } else if os == "windows" { + url = strings.Replace(url, ".tar.gz", ".zip", 1) + } + + url = fmt.Sprintf(url, version, os, version) + } else { + url = fmt.Sprintf(url, version, os, arch) + } if strings.Contains(url, "helm") { if strings.Contains(osArch, "windows") { - url += ".zip" + url += zip } else { - url += ".tar.gz" + url += targz } - } else { + } else if strings.Contains(url, "kubectl") { if strings.Contains(osArch, "windows") { - url += ".exe" + url += exe } } @@ -108,9 +126,9 @@ func SaveBinary(fileName string, body []byte) error { // nolint: funlen file, _ = filepath.Abs(file) if strings.Contains(osArch, "windows") { - fileExt = ".zip" + fileExt = zip } else { - fileExt = ".tar.gz" + fileExt = targz } err = ioutil.WriteFile(file+fileExt, body, 0750) @@ -130,7 +148,55 @@ func SaveBinary(fileName string, body []byte) error { // nolint: funlen path, _ := filepath.Abs(file + fmt.Sprintf("/%s-%s/helm", OS, arch)) if strings.Contains(osArch, "windows") { - path += ".exe" + path += exe + } + + body, err = ioutil.ReadFile(path) + + if err != nil { + return err + } + } else if strings.Contains(fileName, "okd") { + // oc returns a compressed file, so save it somewhere and decompress it + var fileExt string + + rand.Seed(time.Now().UnixNano()) + + randomNumbers := 5000 + tempDir, err := ioutil.TempDir("", "oc") + + if err != nil { + return err + } + // clean temp dir + defer os.RemoveAll(tempDir) + + osArch, _ := GetOSArch() + file := fmt.Sprintf("%s/oc-%s", tempDir, strconv.Itoa(rand.Intn(randomNumbers))) + file, _ = filepath.Abs(file) + + if strings.Contains(osArch, "windows") { + fileExt = zip + } else { + fileExt = targz + } + + err = ioutil.WriteFile(file+fileExt, body, 0750) + + if err != nil { + return err + } + + err = archiver.Unarchive(file+fileExt, file) + + if err != nil { + return err + } + + path, _ := filepath.Abs(file + "/oc") + + if strings.Contains(osArch, "windows") { + path += exe } body, err = ioutil.ReadFile(path) diff --git a/internal/helpers/helpers.go b/internal/helpers/helpers.go index bade06f..1d77ece 100644 --- a/internal/helpers/helpers.go +++ b/internal/helpers/helpers.go @@ -55,6 +55,12 @@ func FileExists(filename string) bool { func GetLastPage(link string) (int, error) { var lastPageInt int var err error + var minLastPage int = 2 + + // When there's no link, it means there's least than 100 releases + if link == "" { + return minLastPage, nil + } link = strings.Split(link, " ")[2] lastPageIndex := strings.LastIndex(link, "page=") @@ -66,7 +72,7 @@ func GetLastPage(link string) (int, error) { } if lastPageInt == 0 { - lastPageInt = 2 + lastPageInt = minLastPage } return lastPageInt, nil diff --git a/tests/managers.test b/tests/managers.test index 7bd78dd..e48434a 100644 --- a/tests/managers.test +++ b/tests/managers.test @@ -9,13 +9,19 @@ function setup() { if [[ ! -e ./bin/kbenv ]] then make build - elif [[ ! -e ./bin/helmenv ]] + elif [[ ! -e ./bin/kubectl-wrapper ]] then make build - elif [[ ! -e ./bin/kubectl-wrapper ]] + elif [[ ! -e ./bin/helmenv ]] then make build elif [[ ! -e ./bin/helm-wrapper ]] + then + make build + elif [[ ! -e ./bin/ocenv ]] + then + make build + elif [[ ! -e ./bin/oc-wrapper ]] then make build fi @@ -28,16 +34,22 @@ function setup() { assert_success run ./bin/helmenv uninstall 3.2.0 assert_success + run ./bin/ocenv uninstall 4.7.0-0.okd-2021-07-03-190901 + assert_success run ./bin/kbenv install 1.18.2 assert_output --partial "Done! Saving it at" run ./bin/helmenv install 3.2.0 assert_output --partial "Done! Saving it at" + run ./bin/ocenv install 4.7.0-0.okd-2021-07-03-190901 + assert_output --partial "Done! Saving it at" run ./bin/kbenv uninstall 1.18.2 assert_success run ./bin/helmenv uninstall 3.2.0 assert_success + run ./bin/ocenv uninstall 4.7.0-0.okd-2021-07-03-190901 + assert_success } @test "uninstall" { @@ -45,11 +57,15 @@ function setup() { assert_success run ./bin/helmenv install 3.2.0 assert_success + run ./bin/ocenv install 4.7.0-0.okd-2021-07-03-190901 + assert_success run ./bin/kbenv uninstall 1.18.2 assert_output --partial "Done! 1.18.2 version uninstalled from" run ./bin/helmenv uninstall 3.2.0 assert_output --partial "Done! 3.2.0 version uninstalled from" + run ./bin/ocenv uninstall 4.7.0-0.okd-2021-07-03-190901 + assert_output --partial "Done! 4.7.0-0.okd-2021-07-03-190901 version uninstalled from" } @test "use" { @@ -57,20 +73,28 @@ function setup() { assert_success run ./bin/helmenv install 3.2.0 assert_success + run ./bin/ocenv install 4.7.0-0.okd-2021-07-03-190901 + assert_success run ./bin/kbenv use 1.18.1 assert_output --partial "Done! Using 1.18.1 version." run ./bin/helmenv use 3.2.0 assert_output --partial "Done! Using 3.2.0 version." + run ./bin/ocenv use 4.7.0-0.okd-2021-07-03-190901 + assert_output --partial "Done! Using 4.7.0-0.okd-2021-07-03-190901 version." run ./bin/kubectl-wrapper version --client assert_output --partial 'GitVersion:"v1.18.1"' run ./bin/helm-wrapper version --client assert_output --partial 'Version:"v3.2.0"' + run ./bin/oc-wrapper version --client + assert_output --partial 'Version: 4.7.0-0.okd-2021-07-03-190901' run ./bin/kbenv uninstall 1.18.1 assert_success run ./bin/helmenv uninstall 3.2.0 assert_success + run ./bin/ocenv uninstall 4.7.0-0.okd-2021-07-03-190901 + assert_success } @test "list local versions" { @@ -78,11 +102,15 @@ function setup() { assert_success run ./bin/helmenv install 3.2.0 assert_success + run ./bin/ocenv install 4.7.0-0.okd-2021-07-03-190901 + assert_success run ./bin/kbenv list local assert_output --partial "1.18.2" run ./bin/helmenv list local assert_output --partial "3.2.0" + run ./bin/ocenv list local + assert_output --partial "4.7.0-0.okd-2021-07-03-190901" } @test "list remote versions" { @@ -99,4 +127,11 @@ function setup() { skip "Attacking Github's API failed, probably because of it's rating. Skipping the test." fi assert_output --partial "3.2.0" + + run ./bin/ocenv list remote --all-versions + if [ "$status" -eq 1 ] + then + skip "Attacking Github's API failed, probably because of it's rating. Skipping the test." + fi + assert_output --partial "4.7.0-0.okd-2021-07-03-190901" } diff --git a/tests/wrappers.test b/tests/wrappers.test index 15f4b4e..aecae0f 100644 --- a/tests/wrappers.test +++ b/tests/wrappers.test @@ -9,13 +9,13 @@ function setup() { if [[ ! -e ./bin/kbenv ]] then make build - elif [[ ! -e ./bin/helmenv ]] + elif [[ ! -e ./bin/kubectl-wrapper ]] then make build - elif [[ ! -e ./bin/kubectl-wrapper ]] + elif [[ ! -e ./bin/ocenv ]] then make build - elif [[ ! -e ./bin/helm-wrapper ]] + elif [[ ! -e ./bin/oc-wrapper ]] then make build fi @@ -23,7 +23,7 @@ function setup() { export PATH=$PATH:$(pwd)/bin/ } -@test "apply" { +@test "kubectl apply" { if [[ "$KIND_CREATE_CLUSTER" == "true" ]] then teardownCallback=$(create_cluster) @@ -31,16 +31,19 @@ function setup() { run ./bin/kbenv install 1.18.1 assert_success - run ./bin/kubectl-wrapper create deployment hello-node --image=k8s.gcr.io/echoserver:1.4 + run ./bin/kubectl-wrapper create deployment hello-node-kubectl --image=k8s.gcr.io/echoserver:1.4 assert_success - pod=$(./bin/kubectl-wrapper get pod -l app=hello-node -o=custom-columns=:.metadata.name | tail -n1) - run ./bin/kubectl-wrapper rollout status deploy hello-node + pod=$(./bin/kubectl-wrapper get pod -l app=hello-node-kubectl -o=custom-columns=:.metadata.name | tail -n1) + run ./bin/kubectl-wrapper rollout status deploy hello-node-kubectl -w assert_success run ./bin/kubectl-wrapper exec "$pod" -- ls assert_success refute_output --partial "Unable to use a TTY" + run ./bin/kubectl-wrapper delete deployment hello-node-kubectl --wait=true + assert_success + run ./bin/kbenv uninstall 1.18.1 assert_success @@ -50,6 +53,37 @@ function setup() { fi } +@test "oc apply" { + if [[ "$KIND_CREATE_CLUSTER" == "true" ]] + then + teardownCallback=$(create_cluster) + fi + + run ./bin/ocenv install 4.7.0-0.okd-2021-07-03-190901 + assert_success + run ./bin/oc-wrapper create deployment hello-node-oc --image=k8s.gcr.io/echoserver:1.4 + assert_success + + pod=$(./bin/oc-wrapper get pod -l app=hello-node-oc -o=custom-columns=:.metadata.name | tail -n1) + run ./bin/oc-wrapper rollout status deploy hello-node-oc -w + assert_success + run ./bin/oc-wrapper exec "$pod" -- ls + assert_success + refute_output --partial "Unable to use a TTY" + + run ./bin/oc-wrapper delete deployment hello-node-oc --wait=true + assert_success + + run ./bin/ocenv uninstall 1.18.1 + assert_success + + if [[ "$KIND_CREATE_CLUSTER" == "true" ]] + then + eval "$teardownCallback" + fi +} + + @test "kubectl auto" { if [[ "$KIND_CREATE_CLUSTER" == "true" ]] then