Skip to content

Commit

Permalink
fix: change how name of the aci is discovered so that the endpoint to…
Browse files Browse the repository at this point in the history
… get the name is hardcoded. When the name is determined it will be cached until aci-exporter is stopped. The name can also be set in the configuration in the fabrics as aci_name, see example_config.yaml
  • Loading branch information
thenodon committed Aug 28, 2023
1 parent eb8aedf commit da40506
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 18 deletions.
23 changes: 19 additions & 4 deletions aci-api.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (

var arrayExtension = regexpcache.MustCompile("^(?P<stage_1>.*)\\.\\[(?P<child_name>.*)\\](?P<stage_2>.*)")

func newAciAPI(ctx context.Context, fabricConfig Fabric, configQueries AllQueries, queryFilter string) *aciAPI {
func newAciAPI(ctx context.Context, fabricConfig *Fabric, configQueries AllQueries, queryFilter string) *aciAPI {

executeQueries := configQueries
queryArray := strings.Split(queryFilter, ",")
Expand Down Expand Up @@ -307,12 +307,27 @@ func (p aciAPI) faults(ch chan []MetricDefinition) {
}

func (p aciAPI) getAciName() (string, error) {
data, err := p.connection.getByQuery("aci_name")
if p.connection.fabricConfig.AciName != "" {
return p.connection.fabricConfig.AciName, nil
}

data, err := p.connection.getByClassQuery("fabricNode", "?query-target-filter=eq(fabricNode.role,\"controller\")")
if err != nil {
return "", err
}

return gjson.Get(data, "imdata.0.infraCont.attributes.fbDmNm").Str, nil
allControllers := gjson.Get(data, "imdata.#.fabricNode.attributes.dn")
for _, controller := range allControllers.Array() {
dataBytes, err := p.connection.get("av", fmt.Sprintf("%s/api/mo/%s/av.json", p.connection.fabricConfig.Apic[*p.connection.activeController], controller.Str))
if err != nil {
continue
}
p.connection.fabricConfig.AciName = gjson.Get(string(dataBytes), "imdata.0.infraCont.attributes.fbDmNm").Str
break
}
if p.connection.fabricConfig.AciName != "" {
return p.connection.fabricConfig.AciName, nil
}
return "", fmt.Errorf("could not determine ACI name")
}

func (p aciAPI) configuredCompoundsMetrics(chall chan []MetricDefinition) {
Expand Down
4 changes: 2 additions & 2 deletions aci-connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ var responseTime = promauto.NewHistogramVec(prometheus.HistogramOpts{
// AciConnection is the connection object
type AciConnection struct {
ctx context.Context
fabricConfig Fabric
fabricConfig *Fabric
activeController *int
URLMap map[string]string
Headers map[string]string
Client http.Client
responseTime *prometheus.HistogramVec
}

func newAciConnction(ctx context.Context, fabricConfig Fabric) *AciConnection {
func newAciConnction(ctx context.Context, fabricConfig *Fabric) *AciConnection {
// Empty cookie jar
jar, _ := cookiejar.New(nil)

Expand Down
25 changes: 15 additions & 10 deletions aci-exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,22 @@ func main() {
log.Error("Unable to decode compound_queries into struct - ", err)
os.Exit(1)
}

allQueries := AllQueries{
ClassQueries: classQueries,
CompoundClassQueries: compoundClassQueries,
GroupClassQueries: groupClassQueries,
}

handler := &HandlerInit{allQueries}
allFabrics := make(map[string]*Fabric)

err = viper.UnmarshalKey("fabrics", &allFabrics)
if err != nil {
log.Error("Unable to decode class_queries into struct - ", err)
os.Exit(1)
}

handler := &HandlerInit{allQueries, allFabrics}

// Create a Prometheus histogram for response time of the exporter
responseTime := promauto.NewHistogramVec(prometheus.HistogramOpts{
Expand Down Expand Up @@ -205,10 +214,11 @@ func cliQuery(fabric *string, class *string, query *string) string {
username := viper.GetString(fmt.Sprintf("fabrics.%s.username", *fabric))
password := viper.GetString(fmt.Sprintf("fabrics.%s.password", *fabric))
apicControllers := viper.GetStringSlice(fmt.Sprintf("fabrics.%s.apic", *fabric))
aciName := viper.GetString(fmt.Sprintf("fabrics.%s.aci_name", *fabric))

fabricConfig := Fabric{Username: username, Password: password, Apic: apicControllers}
fabricConfig := Fabric{Username: username, Password: password, Apic: apicControllers, AciName: aciName}
ctx := context.TODO()
con := *newAciConnction(ctx, fabricConfig)
con := *newAciConnction(ctx, &fabricConfig)
err = con.login()
if err != nil {
fmt.Printf("Login error %s", err)
Expand All @@ -231,6 +241,7 @@ func cliQuery(fabric *string, class *string, query *string) string {

type HandlerInit struct {
AllQueries AllQueries
AllFabrics map[string]*Fabric
}

func (h HandlerInit) getMonitorMetrics(w http.ResponseWriter, r *http.Request) {
Expand All @@ -254,15 +265,9 @@ func (h HandlerInit) getMonitorMetrics(w http.ResponseWriter, r *http.Request) {
return
}

username := viper.GetString(fmt.Sprintf("fabrics.%s.username", fabric))
password := viper.GetString(fmt.Sprintf("fabrics.%s.password", fabric))
apicControllers := viper.GetStringSlice(fmt.Sprintf("fabrics.%s.apic", fabric))

fabricConfig := Fabric{Username: username, Password: password, Apic: apicControllers}

ctx := r.Context()
ctx = context.WithValue(ctx, "fabric", fabric)
api := *newAciAPI(ctx, fabricConfig, h.AllQueries, queries)
api := *newAciAPI(ctx, h.AllFabrics[fabric], h.AllQueries, queries)

aciName, metrics, err := api.CollectMetrics()

Expand Down
2 changes: 2 additions & 0 deletions example-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ fabrics:
apic:
- https://apic1
- https://apic2
# Optional - The name of the aci cluster. If not set, aci-exporter will try to determine the name
aci_name: foobar

# Http client settings used to access apic
# Below is the default values, where 0 is no timeout
Expand Down
5 changes: 3 additions & 2 deletions fabricconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
package main

type Fabric struct {
Username string
Password string
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
Apic []string
AciName string `mapstructure:"aci_name"`
}

0 comments on commit da40506

Please sign in to comment.