Skip to content

Commit

Permalink
Add support showing cluster rate limits
Browse files Browse the repository at this point in the history
  • Loading branch information
talal committed Mar 3, 2023
1 parent bef44d2 commit 711cb36
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 1 deletion.
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,17 @@ The sections should follow the order `Added`, `Changed`, `Fixed`, `Removed`, and
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased](https://github.com/sapcc/limesctl/compare/v3.1.3...HEAD)
## [Unreleased](https://github.com/sapcc/limesctl/compare/v3.2.0...HEAD)

## 3.2.0 - 2023-03-03

## Added

- Support for showing cluster global rate limits.

```
limesctl cluster show-rates
```

## 3.1.3 - 2022-12-15

Expand Down
58 changes: 58 additions & 0 deletions internal/cmd/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package cmd

import (
ratesClusters "github.com/sapcc/gophercloud-sapcc/rates/v1/clusters"
"github.com/sapcc/gophercloud-sapcc/resources/v1/clusters"
"github.com/spf13/cobra"

Expand All @@ -30,6 +31,7 @@ func newClusterCmd() *cobra.Command {
}
doNotSortFlags(cmd)
cmd.AddCommand(newClusterShowCmd().Command)
cmd.AddCommand(newClusterShowRatesCmd().Command)
return cmd
}

Expand Down Expand Up @@ -89,3 +91,59 @@ func (c *clusterShowCmd) Run(_ *cobra.Command, _ []string) error {

return writeReports(outputOpts, core.ClusterReport{ClusterReport: limesRep})
}

///////////////////////////////////////////////////////////////////////////////
// Cluster show rates.

type clusterShowRatesCmd struct {
*cobra.Command

rateFilterFlags
rateOutputFmtFlags
}

func newClusterShowRatesCmd() *clusterShowRatesCmd {
clusterShowRates := &clusterShowRatesCmd{}
cmd := &cobra.Command{
Use: "show-rates",
Short: "Display global rate limits for the cluster",
Long: "Display global rate limits for the cluster level. These rate limits apply to all users in aggregate.",
Args: cobra.NoArgs,
PreRunE: authWithLimesRates,
RunE: clusterShowRates.Run,
}

// Flags
doNotSortFlags(cmd)
clusterShowRates.rateFilterFlags.AddToCmd(cmd)
clusterShowRates.rateOutputFmtFlags.AddToCmd(cmd)

clusterShowRates.Command = cmd
return clusterShowRates
}

func (c *clusterShowRatesCmd) Run(_ *cobra.Command, args []string) error {
outputOpts, err := c.rateOutputFmtFlags.validate()
if err != nil {
return err
}

res := ratesClusters.Get(limesRatesClient, ratesClusters.GetOpts{
Areas: c.areas,
Services: c.services,
})
if res.Err != nil {
return util.WrapError(res.Err, "could not get cluster report")
}

if c.format == core.OutputFormatJSON {
return writeJSON(res.Body)
}

limesRep, err := res.Extract()
if err != nil {
return util.WrapError(err, "could not extract cluster report")
}

return writeReports(outputOpts, core.ClusterRatesReport{ClusterReport: limesRep})
}
77 changes: 77 additions & 0 deletions internal/core/cluster_rates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2020 SAP SE
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package core

import (
"sort"

limesrates "github.com/sapcc/go-api-declarations/limes/rates"
)

// ClusterRatesReport is a wrapper for limesrates.ClusterReport.
type ClusterRatesReport struct {
*limesrates.ClusterReport
}

var csvHeaderClusterRatesDefault = []string{"cluster id", "service", "rate", "limit", "window", "unit"}

var csvHeaderClusterRatesLong = []string{"cluster id", "area", "service", "rate", "limit",
"window", "unit", "scraped at (UTC)"}

func (c ClusterRatesReport) getHeaderRow(opts *OutputOpts) []string {
if opts.CSVRecFmt == CSVRecordFormatLong {
return csvHeaderClusterRatesLong
}
return csvHeaderClusterRatesDefault
}

func (c ClusterRatesReport) render(opts *OutputOpts) CSVRecords {
var records CSVRecords

// Serialize service types with ordered keys
types := make([]string, 0, len(c.Services))
for typeStr := range c.Services {
types = append(types, typeStr)
}
sort.Strings(types)

for _, srv := range types {
// Serialize rate names with ordered keys
names := make([]string, 0, len(c.Services[srv].Rates))
for nameStr := range c.Services[srv].Rates {
names = append(names, nameStr)
}
sort.Strings(names)

for _, rate := range names {
var r []string
// Initialize temporary variables to make map lookups easier.
cSrv := c.Services[srv]
cSrvRate := c.Services[srv].Rates[rate]

valToStr := defaultValToStrFunc
if opts.CSVRecFmt == CSVRecordFormatLong {
r = append(r, c.ID, cSrv.Area, cSrv.Type, cSrvRate.Name, valToStr(cSrvRate.Limit),
cSrvRate.Window.String(), string(cSrvRate.Unit), timestampToString(cSrv.MinScrapedAt))
} else {
r = append(r, c.ID, cSrv.Type, cSrvRate.Name, valToStr(cSrvRate.Limit), cSrvRate.Window.String(), string(cSrvRate.Unit))
}

records = append(records, r)
}
}

return records
}

0 comments on commit 711cb36

Please sign in to comment.