From d69d3166d1aa3ca2afd4d9805767bafdf65bbb1a Mon Sep 17 00:00:00 2001 From: Nicolas Bissig Date: Thu, 20 Jan 2022 17:02:38 +0100 Subject: [PATCH] =?UTF-8?q?Initial=20commit=20=F0=9F=9A=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 24 ++++++ .gitignore | 2 + .goreleaser.yaml | 41 +++++++++ go.mod | 3 + main.go | 155 ++++++++++++++++++++++++++++++++++ readme.md | 18 ++++ 6 files changed, 243 insertions(+) create mode 100644 .github/workflows/release.yml create mode 100644 .gitignore create mode 100644 .goreleaser.yaml create mode 100644 go.mod create mode 100644 main.go create mode 100644 readme.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..a726ec3 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,24 @@ +name: release + +on: + push: + tags: + - v* + +jobs: + goreleaser: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.17 + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v2 + with: + version: latest + args: release --rm-dist --debug + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5cb6357 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +dist/ +.idea/ diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..664dfbf --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,41 @@ +builds: + - env: + - CGO_ENABLED=0 + goos: + - linux + - windows + - darwin +archives: + - replacements: + darwin: Darwin + linux: Linux + windows: Windows + 386: i386 + amd64: x86_64 +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "{{ incpatch .Version }}-next" +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' + +brews: + - tap: + owner: deviceinsight + name: homebrew-packages + + commit_author: + name: goreleaserbot + email: goreleaser@device-insight.com + + folder: Formula + homepage: https://www.device-insight.com/ + + description: | + azctx is a command line tool whose aim is to ease the use of the official az cli. It is heavily inspired by kubectx. + + skip_upload: "false" diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8b1b9c9 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/deviceinsight/azctx + +go 1.17 diff --git a/main.go b/main.go new file mode 100644 index 0000000..37bc870 --- /dev/null +++ b/main.go @@ -0,0 +1,155 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "os" + "os/exec" + "strings" +) + +type Account struct { + ID string `json:"id"` + IsDefault bool `json:"isDefault"` + Name string `json:"name"` +} + +type Group struct { + ID string `json:"id"` + Name string `json:"name"` +} + +type AzConfig struct { + Defaults []struct { + Name string `json:"name"` + Value string `json:"value"` + } `json:"defaults"` +} + +var ( + azCli = "az" + GreenColor = "\033[1;32m%s\033[0m\n" +) + +func main() { + selectedAccount := withFilter("Subscription", func(in io.WriteCloser) { + accounts, err := getAllAccounts() + if err != nil { + in.Close() + return + } + for _, account := range accounts { + if account.IsDefault { + fmt.Fprintf(in, GreenColor, account.Name) + } else { + fmt.Fprintln(in, account.Name) + } + } + }) + + if selectedAccount == "" { + return + } + + selectedGroup := withFilter("Resource group (Cancel for none)", func(in io.WriteCloser) { + setAccount(selectedAccount) + groups, err := getGroups() + if err != nil { + in.Close() + return + } + defaultGroup := getDefaultGroup() + for _, group := range groups { + if group.Name == defaultGroup { + fmt.Fprintf(in, GreenColor, group.Name) + } else { + fmt.Fprintln(in, group.Name) + } + } + in.Close() + }) + setGroup(selectedGroup) + + conclusion := "Switched to subscription \"" + selectedAccount + "\" " + if selectedGroup != "" { + conclusion += "and resource group \"" + selectedGroup + "\"" + } else { + conclusion += "and no resource group" + } + fmt.Println(conclusion) +} + +func getAllAccounts() ([]Account, error) { + output, execErr := exec.Command(azCli, "account", "list").Output() + if execErr != nil { + return nil, execErr + } + var accounts []Account + jsonErr := json.Unmarshal(output, &accounts) + if jsonErr != nil { + return nil, execErr + } + return accounts, nil +} + +func setAccount(accountName string) error { + execErr := exec.Command(azCli, "account", "set", "--subscription", accountName).Run() + if execErr != nil { + return execErr + } + return nil +} + +func getDefaultGroup() string { + output, execErr := exec.Command(azCli, "config", "get").Output() + if execErr != nil { + return "" + } + var config AzConfig + jsonErr := json.Unmarshal(output, &config) + if jsonErr != nil { + return "" + } + defaultGroup := "" + for _, option := range config.Defaults { + if option.Name == "group" { + return option.Value + } + } + return defaultGroup +} + +func getGroups() ([]Group, error) { + output, execErr := exec.Command(azCli, "group", "list").Output() + if execErr != nil { + return nil, execErr + } + var groups []Group + jsonErr := json.Unmarshal(output, &groups) + if jsonErr != nil { + return nil, jsonErr + } + return groups, nil +} + +func setGroup(groupName string) { + exec.Command(azCli, "config", "set", "defaults.group="+groupName).Run() +} + +// https://junegunn.kr/2016/02/using-fzf-in-your-program/ +func withFilter(header string, input func(in io.WriteCloser)) string { + shell := os.Getenv("SHELL") + if len(shell) == 0 { + shell = "sh" + } + cmd := exec.Command(shell, "-c", "fzf --ansi --layout=reverse --header=\""+header+"\"") + cmd.Stderr = os.Stderr + cmdIn, _ := cmd.StdinPipe() + go func() { + input(cmdIn) + cmdIn.Close() + }() + result, _ := cmd.Output() + return strings.ReplaceAll(string(result), "\n", "") +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..1bc343f --- /dev/null +++ b/readme.md @@ -0,0 +1,18 @@ +# azctx: Azure context + +`azctx` is a command line tool whose aim is to ease the use of the +official [az cli](https://docs.microsoft.com/en-us/cli/azure/). It is heavily inspired +by [kubectx](https://github.com/ahmetb/kubectx). + +It provides an easier and more intuitive way to set your current default azure subscription/account and resource group. + +## Requirements + +- [az cli](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) +- [fzf](https://github.com/junegunn/fzf) + +## Usage + +- Run `azctx` +- Select a Subscription/Account, (Arrow keys, Search, Enter, Double click) +- Select resource group, or quit (CTRL + C) if you don't want to/clear the default resource group \ No newline at end of file