Skip to content

Commit

Permalink
Chore: clean-up code
Browse files Browse the repository at this point in the history
  • Loading branch information
till committed Jan 27, 2022
1 parent d33f69a commit fd69037
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 91 deletions.
102 changes: 11 additions & 91 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,105 +1,29 @@
package main

import (
"encoding/base64"
"fmt"
"os"

"github.com/go-resty/resty/v2"
"github.com/Luzilla/acronis-s3-usage/pkg/acronis"
)

func encodeClientCredentials() string {
authStr := fmt.Sprintf("%s:%s",
func main() {
aci := acronis.NewClient(
os.Getenv("ACI_CLIENT_ID"),
os.Getenv("ACI_SECRET"),
os.Getenv("ACI_DC_URL"),
)
return base64.StdEncoding.EncodeToString([]byte(authStr))
}

func buildBearer(tokenData tokenResponse) string {
return fmt.Sprintf("Bearer %s", tokenData.AccessToken)
}

type tokenResponse struct {
AccessToken string `json:"access_token"`
ExpiresOn int64 `json:"expires_on"`
IdToken string `json:"id_token"`
TokenType string `json:"token_type"`
}

type clientResponse struct {
TenantID string `json:"tenant_id"`
}

type usageItem struct {
Tenant string `json:"tenant"`
Usages []map[string]interface{} `json:"usages"`
}

type usageResponse struct {
Items []usageItem `json:"items"`
}

type applicationResponse struct {
Id string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
}

func main() {
client := resty.New()
client.SetBaseURL(fmt.Sprintf("%s/api/2", os.Getenv("ACI_DC_URL")))
client.SetHeader("Accept", "application/json")

// fetch token
var tokenData tokenResponse
resp, err := client.R().
SetHeader("Authorization", fmt.Sprintf("Basic %s", encodeClientCredentials())).
SetHeader("Content-Type", "application/x-www-form-urlencoded").
SetFormData(map[string]string{"grant_type": "client_credentials"}).
SetResult(&tokenData).
Post("/idp/token")
tenantId, err := aci.GetTenantID()
if err != nil {
panic(err)
}
fmt.Printf("Got tenant id: %s\n", tenantId)

if !resp.IsSuccess() {
fmt.Println("Unable to fetch token.")
fmt.Printf("%v", string(resp.Body()))
os.Exit(-1)
}

fmt.Printf("Got a token: %s***\n", tokenData.AccessToken[0:6])
client.SetHeader("Authorization", buildBearer(tokenData))

// fetch tenant id
var clientData clientResponse
resp, err = client.R().
SetResult(&clientData).
Get(fmt.Sprintf("/clients/%s", os.Getenv("ACI_CLIENT_ID")))
usageData, err := aci.GetUsage(tenantId)
if err != nil {
panic(err)
}
if !resp.IsSuccess() {
fmt.Println("Unable to fetch tenant id")
os.Exit(-1)
}

fmt.Printf("Got tenant id: %s\n", clientData.TenantID)

// fetch usage data
var usageData usageResponse
resp, err = client.R().
SetQueryParams(map[string]string{"tenants": clientData.TenantID}).
SetResult(&usageData).
Get("/tenants/usages")
if err != nil {
panic(err)
}
if !resp.IsSuccess() {
fmt.Println("Unable to fetch usage data.")
os.Exit(-1)
}

for _, items := range usageData.Items {
//fmt.Printf("Got tenant ID: %s\n", items.Tenant)
Expand All @@ -108,17 +32,13 @@ func main() {
continue
}

var applicationData applicationResponse
resp, err = client.R().
SetResult(&applicationData).
Get(fmt.Sprintf("/applications/%s", usages["application_id"]))
if !resp.IsSuccess() {
app, err := aci.GetApplication(usages["application_id"].(string))
if err != nil {
panic(err)
}

fmt.Printf("%s (Type: %s)\n\n%s -- %.2f GB\n",
applicationData.Name,
applicationData.Type,
app.Name,
app.Type,
usages["name"],
// bitshift -> byte to gb
(usages["absolute_value"].(float64) / (1 << 30)))
Expand Down
120 changes: 120 additions & 0 deletions pkg/acronis/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package acronis

import (
"encoding/base64"
"fmt"
"os"

"github.com/go-resty/resty/v2"
)

type AcronisClient struct {
ClientID string
Secret string
DCurl string
token tokenResponse
http *resty.Client
}

func NewClient(clientID string, secret string, dcURL string) *AcronisClient {
http := resty.New()
http.SetBaseURL(fmt.Sprintf("%s/api/2", dcURL))
http.SetHeader("Accept", "application/json")

return &AcronisClient{
ClientID: clientID,
Secret: secret,
DCurl: dcURL,
http: http,
}
}

func (c *AcronisClient) GetApplication(appId string) (ApplicationResponse, error) {
var data ApplicationResponse
resp, err := c.http.R().
SetResult(&data).
Get(fmt.Sprintf("/applications/%s", appId))
if !resp.IsSuccess() {
return ApplicationResponse{}, err
}

return data, nil
}

// fetch tenant id
func (c *AcronisClient) GetTenantID() (string, error) {
c.fetchToken()

var data clientResponse
resp, err := c.http.R().
SetResult(&data).
Get(fmt.Sprintf("/clients/%s", os.Getenv("ACI_CLIENT_ID")))
if err != nil {
return "", err
}
if !resp.IsSuccess() {
return "", fmt.Errorf("unable to fetch tenant id: %s", resp.Body())
}

return data.TenantID, nil
}

// fetch usage data
func (c *AcronisClient) GetUsage(tenantId string) (UsageResponse, error) {
c.fetchToken()

var data UsageResponse
resp, err := c.http.R().
SetQueryParams(map[string]string{"tenants": tenantId}).
SetResult(&data).
Get("/tenants/usages")
if err != nil {
return UsageResponse{}, err
}
if !resp.IsSuccess() {
return UsageResponse{}, fmt.Errorf("unable to fetch usage data: %s", resp.Body())
}

return data, nil
}

func (c *AcronisClient) encodeClientCredentials() string {
authStr := fmt.Sprintf("%s:%s",
c.ClientID,
c.Secret,
)
return base64.StdEncoding.EncodeToString([]byte(authStr))
}

func (c *AcronisClient) buildBearer() string {
return fmt.Sprintf("Bearer %s", c.token.AccessToken)
}

func (c *AcronisClient) fetchToken() {
if c.token.AccessToken != "" {
return
}

// fetch token
var tokenData tokenResponse
resp, err := c.http.R().
SetHeader("Authorization", fmt.Sprintf("Basic %s", c.encodeClientCredentials())).
SetHeader("Content-Type", "application/x-www-form-urlencoded").
SetFormData(map[string]string{"grant_type": "client_credentials"}).
SetResult(&tokenData).
Post("/idp/token")
if err != nil {
panic(err)
}

if !resp.IsSuccess() { // FIXME
fmt.Println("Unable to fetch token.")
fmt.Printf("%v", string(resp.Body()))
os.Exit(-1)
}

c.token = tokenData

fmt.Printf("Got a token: %s***\n", c.token.AccessToken[0:8])
c.http.SetHeader("Authorization", c.buildBearer())
}
27 changes: 27 additions & 0 deletions pkg/acronis/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package acronis

type ApplicationResponse struct {
Id string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
}

type UsageItem struct {
Tenant string `json:"tenant"`
Usages []map[string]interface{} `json:"usages"`
}

type UsageResponse struct {
Items []UsageItem `json:"items"`
}

type clientResponse struct {
TenantID string `json:"tenant_id"`
}

type tokenResponse struct {
AccessToken string `json:"access_token"`
ExpiresOn int64 `json:"expires_on"`
IdToken string `json:"id_token"`
TokenType string `json:"token_type"`
}

0 comments on commit fd69037

Please sign in to comment.