Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugins designate: convert to gophercloud #128

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ require (
google.golang.org/protobuf v1.28.0 // indirect
)

replace github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.24.1-0.20220510134014-0ffab06fc18e
replace github.com/gophercloud/gophercloud => github.com/sapcc/gophercloud v0.0.0-20220510151119-9b193d901d47
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,6 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/gophercloud/gophercloud v0.24.1-0.20220510134014-0ffab06fc18e h1:QvfpchVi0LFbru2XDkeSAMdiyrAFZ1clhTo8Xai5sQY=
github.com/gophercloud/gophercloud v0.24.1-0.20220510134014-0ffab06fc18e/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c=
github.com/gophercloud/utils v0.0.0-20210323225332-7b186010c04f/go.mod h1:wx8HMD8oQD0Ryhz6+6ykq75PJ79iPyEqYHfwZ4l7OsA=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
Expand Down Expand Up @@ -853,6 +851,8 @@ github.com/sapcc/go-api-declarations v1.1.0 h1:xZDnW0LmpAqCX7j8TJ+V3gnBmV4CjXviF
github.com/sapcc/go-api-declarations v1.1.0/go.mod h1:zS+2xqmbtAyQxQz1liJp0qxDgop78fb4Sfk/IB0PvH0=
github.com/sapcc/go-bits v0.0.0-20220506231902-df94414a6255 h1:8wnKs4Xl/hpqXLSfTr0sRvyWLOQ1uIdXWLnYZEH2RhA=
github.com/sapcc/go-bits v0.0.0-20220506231902-df94414a6255/go.mod h1:51WQyNfN61ASvq05jvwF2Z7WmJKxiQd0SHttXu+hKKw=
github.com/sapcc/gophercloud v0.0.0-20220510151119-9b193d901d47 h1:cF3M1IVubrHm+dzVs8Wr3iI8tSlfk9GwH/CrBi9RRbY=
github.com/sapcc/gophercloud v0.0.0-20220510151119-9b193d901d47/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
Expand Down
100 changes: 33 additions & 67 deletions pkg/plugins/designate.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (

"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/gophercloud/openstack/dns/v2/quotas"
"github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets"
"github.com/gophercloud/gophercloud/openstack/dns/v2/zones"
"github.com/gophercloud/gophercloud/pagination"
"github.com/prometheus/client_golang/prometheus"
Expand Down Expand Up @@ -91,7 +93,8 @@ func (p *designatePlugin) Scrape(provider *gophercloud.ProviderClient, eo gopher
}

//query quotas
quotas, err := dnsGetQuota(client, project.UUID)
client.MoreHeaders = map[string]string{"X-Auth-All-Projects": "true"}
quotas, err := quotas.Get(client, project.UUID).Extract()
if err != nil {
return nil, "", err
}
Expand All @@ -105,25 +108,33 @@ func (p *designatePlugin) Scrape(provider *gophercloud.ProviderClient, eo gopher
//query "recordsets per zone" usage by counting recordsets in each zone
//individually (we could count all recordsets over the all project at once,
//but that won't help since the quota applies per individual zone)
maxRecordsetsPerZone := uint64(0)
maxRecordsetsPerZone := 0
for _, zoneID := range zoneIDs {
count, err := dnsCountZoneRecordsets(client, project.UUID, zoneID)
client.MoreHeaders = map[string]string{
"X-Auth-All-Projects": "false",
"X-Auth-Sudo-Project-Id": project.UUID,
}
allZones, err := recordsets.ListByZone(client, zoneID, recordsets.ListOpts{Limit: 1}).AllPages()
if err != nil {
return nil, "", err
}
if maxRecordsetsPerZone < count {
maxRecordsetsPerZone = count
allRecordSets, err := recordsets.ExtractRecordSets(allZones)
if err != nil {
return nil, "", err
}
if maxRecordsetsPerZone < allRecordSets[0].Metadata.TotalCount {
maxRecordsetsPerZone = allRecordSets[0].Metadata.TotalCount
}
}

return map[string]core.ResourceData{
"zones": {
Quota: quotas.Zones,
Quota: int64(quotas.Zones),
Usage: uint64(len(zoneIDs)),
},
"recordsets": {
Quota: quotas.ZoneRecordsets,
Usage: maxRecordsetsPerZone,
Quota: int64(quotas.ZoneRecordsets),
Usage: uint64(maxRecordsetsPerZone),
},
}, "", nil
}
Expand All @@ -135,20 +146,27 @@ func (p *designatePlugin) IsQuotaAcceptableForProject(client *gophercloud.Provid
}

//SetQuota implements the core.QuotaPlugin interface.
func (p *designatePlugin) SetQuota(provider *gophercloud.ProviderClient, eo gophercloud.EndpointOpts, project core.KeystoneProject, quotas map[string]uint64) error {
func (p *designatePlugin) SetQuota(provider *gophercloud.ProviderClient, eo gophercloud.EndpointOpts, project core.KeystoneProject, quota map[string]uint64) error {
client, err := openstack.NewDNSV2(provider, eo)
if err != nil {
return err
}

return dnsSetQuota(client, project.UUID, &dnsQuota{
Zones: int64(quotas["zones"]),
ZoneRecordsets: int64(quotas["recordsets"]),
uint2p := func(val uint64) *int {
ret := int(val)
return &ret
}

client.MoreHeaders = map[string]string{"X-Auth-All-Projects": "true"}
_, err = quotas.Update(client, project.UUID, quotas.UpdateOpts{
Zones: uint2p(quota["zones"]),
ZoneRecordsets: uint2p(quota["recordsets"]),
//set ZoneRecords quota to match ZoneRecordsets
//(Designate has a records_per_recordset quota of default 20, so if we set
//ZoneRecords to 20 * ZoneRecordsets, this quota will not disturb us)
ZoneRecords: int64(quotas["recordsets"] * 20),
})
ZoneRecords: uint2p(quota["recordsets"] * 20),
}).Extract()
return err
}

//DescribeMetrics implements the core.QuotaPlugin interface.
Expand All @@ -165,38 +183,9 @@ func (p *designatePlugin) CollectMetrics(ch chan<- prometheus.Metric, clusterID
////////////////////////////////////////////////////////////////////////////////
// API requests to Designate

type dnsQuota struct {
Zones int64 `json:"zones"`
ZoneRecordsets int64 `json:"zone_recordsets"`
ZoneRecords int64 `json:"zone_records"`
}

func dnsGetQuota(client *gophercloud.ServiceClient, projectUUID string) (*dnsQuota, error) {
url := client.ServiceURL("quotas", projectUUID)
opts := gophercloud.RequestOpts{
MoreHeaders: map[string]string{"X-Auth-All-Projects": "true"},
}

var result gophercloud.Result
var data dnsQuota
_, result.Err = client.Get(url, &result.Body, &opts)
err := result.ExtractInto(&data)
return &data, err
}

func dnsSetQuota(client *gophercloud.ServiceClient, projectUUID string, quota *dnsQuota) error {
url := client.ServiceURL("quotas", projectUUID)
opts := gophercloud.RequestOpts{
MoreHeaders: map[string]string{"X-Auth-All-Projects": "true"},
}

_, err := client.Patch(url, quota, nil, &opts)
return err
}

func dnsListZoneIDs(client *gophercloud.ServiceClient, projectUUID string) ([]string, error) {
pager := zones.List(client, zones.ListOpts{})
pager.Headers = map[string]string{
client.MoreHeaders = map[string]string{
"X-Auth-All-Projects": "false",
"X-Auth-Sudo-Project-Id": projectUUID,
}
Expand All @@ -214,26 +203,3 @@ func dnsListZoneIDs(client *gophercloud.ServiceClient, projectUUID string) ([]st
})
return ids, err
}

func dnsCountZoneRecordsets(client *gophercloud.ServiceClient, projectUUID, zoneID string) (uint64, error) {
url := client.ServiceURL("zones", zoneID, "recordsets")
opts := gophercloud.RequestOpts{
MoreHeaders: map[string]string{
"X-Auth-All-Projects": "false",
"X-Auth-Sudo-Project-Id": projectUUID,
},
}

//do not need all data about all recordsets, just the total count
url += "?limit=1"

var result gophercloud.Result
var data struct {
Metadata struct {
Count uint64 `json:"total_count"`
} `json:"metadata"`
}
_, result.Err = client.Get(url, &result.Body, &opts)
err := result.ExtractInto(&data)
return data.Metadata.Count, err
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading