Skip to content

Commit

Permalink
fix 🐛: some issues with monthly pricing
Browse files Browse the repository at this point in the history
  • Loading branch information
muandane committed Oct 13, 2023
1 parent 991f378 commit 609bd25
Show file tree
Hide file tree
Showing 82 changed files with 14,136 additions and 137 deletions.
2 changes: 1 addition & 1 deletion src/.goreleaser.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
builds:
- binary: azureprice
main: ./cmd
main: ./
goos:
- darwin
- linux
Expand Down
134 changes: 0 additions & 134 deletions src/cmd/main.go

This file was deleted.

153 changes: 153 additions & 0 deletions src/cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package cmd

import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"strings"

"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/lipgloss/table"
"github.com/spf13/cobra"
)

type Item struct {
ArmRegionName string `json:"armRegionName"`
ArmSkuName string `json:"armSkuName"`
MeterName string `json:"meterName"`
ProductName string `json:"productName"`
RetailPrice float64 `json:"retailPrice"`
UnitOfMeasure string `json:"unitOfMeasure"`
}

type Response struct {
Items []Item `json:"Items"`
NextPageLink string `json:"NextPageLink"`
}

var vmType string
var region string
var service string
var pricingType string
var currency string

var rootCmd = &cobra.Command{
Use: "azureprice",
Short: "Azure Prices CLI",
Long: `azureprice is a Go CLI that retrieves pricing information for Azure services using the Azure pricing API.`,
Run: func(cmd *cobra.Command, args []string) {
re := lipgloss.NewRenderer(os.Stdout)
baseStyle := re.NewStyle().Padding(0, 1)
headerStyle := baseStyle.Copy().Foreground(lipgloss.AdaptiveColor{Light: "#186F65", Dark: "#1AACAC"}).Bold(true)
typeColors := map[string]lipgloss.AdaptiveColor{
"Spot": lipgloss.AdaptiveColor{Light: "#D83F31", Dark: "#D83F31"},
"Normal": lipgloss.AdaptiveColor{Light: "#116D6E", Dark: "#00DFA2"},
"Low": lipgloss.AdaptiveColor{Light: "#EE9322", Dark: "#E9B824"},
}

var query string
if service != "" {
query = fmt.Sprintf("armRegionName eq '%s' and contains(serviceName, '%s')", region, service)
} else if vmType != "" {
query = fmt.Sprintf("armRegionName eq '%s' and contains(armSkuName, '%s') and priceType eq '%s'", region, vmType, pricingType)
} else {
fmt.Println("Please provide either a series or type flag.")
return
}

tableData := [][]string{{"SKU", "Retail Price", "Unit of Measure", "Monthly Price", "Region", "Meter", "Product Name"}}
apiURL := "https://prices.azure.com/api/retail/prices?"
currencyType := fmt.Sprintf("currencyCode='%s'", currency)

for {
var resp Response
err := getJSON(apiURL+currencyType+"&$filter="+url.QueryEscape(query), &resp)
if err != nil {
fmt.Println("Error:", err)
return
}

for _, item := range resp.Items {
var monthlyPrice string
if pricingType != "Reservation" {
monthlyPrice = fmt.Sprintf("%v", item.RetailPrice*730) // Calculate the monthly price
} else {
monthlyPrice = "---"
}
tableData = append(tableData, []string{item.ArmSkuName, fmt.Sprintf("%f", item.RetailPrice), item.UnitOfMeasure, fmt.Sprintf("%v", monthlyPrice), item.ArmRegionName, item.MeterName, item.ProductName})
}
if resp.NextPageLink == "" {
break
}
apiURL = resp.NextPageLink
}

headers := []string{"SKU", "Retail Price", "Unit of Measure", "Monthly Price", "Region", "Meter", "Product Name"}
CapitalizeHeaders := func(tableData []string) []string {
for i := range tableData {
tableData[i] = strings.ToUpper(tableData[i])
}
return tableData
}

t := table.New().
Border(lipgloss.NormalBorder()).
BorderStyle(re.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#186F65", Dark: "#1AACAC"})).
Headers(CapitalizeHeaders(headers)...).
Width(120).
Rows(tableData[1:]...). // Pass only the rows to the Rows function
StyleFunc(func(row, col int) lipgloss.Style {
if row == 0 {
return headerStyle
}
if col == 4 {
// Check if the "Meter" column contains "Spot" or "Low"
meter := tableData[row-0][4] // The "Meter" column is the 5th column (index 4)
color := lipgloss.AdaptiveColor{Light: "#186F65", Dark: "#1AACAC"} // Default color
if strings.Contains(meter, "Spot") {
color = typeColors["Spot"]
} else if strings.Contains(meter, "Low") {
color = typeColors["Low"]
} else {
color = typeColors["Normal"]
}
return baseStyle.Copy().Foreground(color)
}
return baseStyle.Copy().Foreground(lipgloss.AdaptiveColor{Light: "#053B50", Dark: "#F1EFEF"})
})
fmt.Println(t)
},
}

func init() {
rootCmd.Flags().StringVarP(&vmType, "type", "t", "Standard_B4ms", "VM type")
rootCmd.Flags().StringVarP(&region, "region", "r", "westus", "Region")
rootCmd.Flags().StringVarP(&service, "service", "s", "", "Azure service (e.g., 'D' for D series vms, Private for Private links)")
rootCmd.Flags().StringVarP(&pricingType, "pricing-type", "p", "Consumption", "Pricing Type (e.g., 'Consumption' or 'Reservation')")
rootCmd.Flags().StringVarP(&currency, "currency", "c", "USD", "Price Currency (e.g., 'USD' or 'EUR')")
}

func getJSON(url string, v interface{}) error {
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}

return json.Unmarshal(body, v)
}

func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
9 changes: 7 additions & 2 deletions src/go.mod
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
module azureprice
module github.com/muandane/azureprice

go 1.21.3

require github.com/charmbracelet/lipgloss v0.9.1
require (
github.com/charmbracelet/lipgloss v0.9.1
github.com/spf13/cobra v1.7.0
)

require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/sys v0.12.0 // indirect
)
10 changes: 10 additions & 0 deletions src/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg=
github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
Expand All @@ -16,6 +19,13 @@ github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1n
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
9 changes: 9 additions & 0 deletions src/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package main

import (
"github.com/muandane/azureprice/cmd"
)

func main() {
cmd.Execute()
}
Loading

0 comments on commit 609bd25

Please sign in to comment.