Skip to content

Commit

Permalink
Initial commit 🚢
Browse files Browse the repository at this point in the history
  • Loading branch information
nbi-di committed Jan 20, 2022
0 parents commit d69d316
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 0 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -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 }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist/
.idea/
41 changes: 41 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -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: [email protected]

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"
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/deviceinsight/azctx

go 1.17
155 changes: 155 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -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", "")
}
18 changes: 18 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit d69d316

Please sign in to comment.