Skip to content
Merged
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
68 changes: 64 additions & 4 deletions acceptance/openstack/rms/v1/compliance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,84 @@ func TestComplianceList(t *testing.T) {
ruleName := tools.RandomString("rule-", 4)
rule := createRule(t, client, ruleName)

// Test ListAllCompliance
th.AssertNoErr(t, waitForRuleAvailable(client, 120, client.DomainID, rule.ID))

// Use small limit to trigger pagination across existing resources
limit := 100
listOpts := compliance.ListAllComplianceOpts{
DomainId: client.DomainID,
PolicyId: rule.ID,
Limit: &limit,
}

allCompliance, err := compliance.ListAllRuleCompliance(client, listOpts)
th.AssertNoErr(t, err)
th.AssertEquals(t, true, len(allCompliance) > 0)
t.Logf("ListAllRuleCompliance returned %d results (limit=%d)", len(allCompliance), limit)

// Test ListAllUserCompliance
// Test ListAllUserCompliance with small limit
userComplianceOpts := compliance.ListAllUserComplianceOpts{
DomainId: client.DomainID,
Limit: &limit,
}

userCompliance, err := compliance.ListAllUserCompliance(client, userComplianceOpts)
th.AssertNoErr(t, err)
th.AssertEquals(t, true, len(userCompliance) > 0)
t.Logf("ListAllUserCompliance returned %d results (limit=%d)", len(userCompliance), limit)

// Test filtering by compliance_state
compliantOpts := compliance.ListAllComplianceOpts{
DomainId: client.DomainID,
PolicyId: rule.ID,
ComplianceState: "Compliant",
}
compliantStates, err := compliance.ListAllRuleCompliance(client, compliantOpts)
th.AssertNoErr(t, err)
for _, s := range compliantStates {
th.AssertEquals(t, "Compliant", s.ComplianceState)
}
t.Logf("Compliant filter returned %d results", len(compliantStates))

nonCompliantOpts := compliance.ListAllComplianceOpts{
DomainId: client.DomainID,
PolicyId: rule.ID,
ComplianceState: "NonCompliant",
}
nonCompliantStates, err := compliance.ListAllRuleCompliance(client, nonCompliantOpts)
th.AssertNoErr(t, err)
for _, s := range nonCompliantStates {
th.AssertEquals(t, "NonCompliant", s.ComplianceState)
}
t.Logf("NonCompliant filter returned %d results", len(nonCompliantStates))

// Test filtering by resource_name
if len(allCompliance) > 0 {
targetName := allCompliance[0].ResourceName
nameOpts := compliance.ListAllComplianceOpts{
DomainId: client.DomainID,
PolicyId: rule.ID,
ResourceName: targetName,
}
nameStates, err := compliance.ListAllRuleCompliance(client, nameOpts)
th.AssertNoErr(t, err)
for _, s := range nameStates {
th.AssertEquals(t, targetName, s.ResourceName)
}
t.Logf("ResourceName filter '%s' returned %d results", targetName, len(nameStates))

// Test filtering by resource_id
targetID := allCompliance[0].ResourceID
idOpts := compliance.ListAllComplianceOpts{
DomainId: client.DomainID,
PolicyId: rule.ID,
ResourceId: targetID,
}
idStates, err := compliance.ListAllRuleCompliance(client, idOpts)
th.AssertNoErr(t, err)
for _, s := range idStates {
th.AssertEquals(t, targetID, s.ResourceID)
}
t.Logf("ResourceId filter '%s' returned %d results", targetID, len(idStates))
}

// Test ListResCompliance
resComplianceOpts := compliance.ListResComplianceOpts{
Expand Down
2 changes: 1 addition & 1 deletion acceptance/openstack/rms/v1/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func TestRecorderResourceList(t *testing.T) {
listOpts,
)
th.AssertNoErr(t, err)
th.AssertEquals(t, 0, len(resources))
th.AssertEquals(t, true, len(resources) > 0)
}

func TestServicesList(t *testing.T) {
Expand Down
10 changes: 8 additions & 2 deletions openstack/rms/compliance/ListAllRuleCompliance.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,18 @@ type ListAllComplianceOpts struct {

func ListAllRuleCompliance(client *golangsdk.ServiceClient, opts ListAllComplianceOpts) ([]PolicyState, error) {
// GET /v1/resource-manager/domains/{domain_id}/policy-assignments/{policy_assignment_id}/policy-states
url, err := golangsdk.NewURLBuilder().
WithEndpoints("resource-manager", "domains", opts.DomainId, "policy-assignments", opts.PolicyId, "policy-states").
WithQueryParams(&opts).Build()
if err != nil {
return nil, err
}

pages, err := pagination.Pager{
Client: client,
InitialURL: client.ServiceURL("resource-manager", "domains", opts.DomainId, "policy-assignments", opts.PolicyId, "policy-states"),
InitialURL: client.ServiceURL(url.String()),
CreatePage: func(r pagination.NewPageResult) pagination.NewPage {
return ResPage{NewSinglePageBase: pagination.NewSinglePageBase{NewPageResult: r}}
return CompliancePage{NewPageInfoBase: pagination.NewPageInfoBase{NewPageResult: r}}
},
}.NewAllPages()
if err != nil {
Expand Down
12 changes: 9 additions & 3 deletions openstack/rms/compliance/ListAllUserCompliance.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,19 @@ type ListAllUserComplianceOpts struct {
}

func ListAllUserCompliance(client *golangsdk.ServiceClient, opts ListAllUserComplianceOpts) ([]PolicyState, error) {
// GET /v1/resource-manager/domains/{domain_id}/policy-assignments/{policy_assignment_id}/policy-states
// GET /v1/resource-manager/domains/{domain_id}/policy-states
url, err := golangsdk.NewURLBuilder().
WithEndpoints("resource-manager", "domains", opts.DomainId, "policy-states").
WithQueryParams(&opts).Build()
if err != nil {
return nil, err
}

pages, err := pagination.Pager{
Client: client,
InitialURL: client.ServiceURL("resource-manager", "domains", opts.DomainId, "policy-states"),
InitialURL: client.ServiceURL(url.String()),
CreatePage: func(r pagination.NewPageResult) pagination.NewPage {
return ResPage{NewSinglePageBase: pagination.NewSinglePageBase{NewPageResult: r}}
return CompliancePage{NewPageInfoBase: pagination.NewPageInfoBase{NewPageResult: r}}
},
}.NewAllPages()
if err != nil {
Expand Down
16 changes: 13 additions & 3 deletions openstack/rms/compliance/ListResCompliance.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ type ListResComplianceOpts struct {

func ListResCompliance(client *golangsdk.ServiceClient, opts ListResComplianceOpts) ([]PolicyState, error) {
// GET /v1/resource-manager/domains/{domain_id}/resources/{resource_id}/policy-states
url, err := golangsdk.NewURLBuilder().
WithEndpoints("resource-manager", "domains", opts.DomainId, "resources", opts.ResourceId, "policy-states").
WithQueryParams(&opts).Build()
if err != nil {
return nil, err
}

pages, err := pagination.Pager{
Client: client,
InitialURL: client.ServiceURL("resource-manager", "domains", opts.DomainId, "resources", opts.ResourceId, "policy-states"),
InitialURL: client.ServiceURL(url.String()),
CreatePage: func(r pagination.NewPageResult) pagination.NewPage {
return ResPage{NewSinglePageBase: pagination.NewSinglePageBase{NewPageResult: r}}
return CompliancePage{NewPageInfoBase: pagination.NewPageInfoBase{NewPageResult: r}}
},
}.NewAllPages()
if err != nil {
Expand All @@ -35,11 +41,15 @@ func ListResCompliance(client *golangsdk.ServiceClient, opts ListResComplianceOp
return ExtractComplianceState(pages)
}

type CompliancePage struct {
pagination.NewPageInfoBase
}

func ExtractComplianceState(r pagination.NewPage) ([]PolicyState, error) {
var s struct {
Values []PolicyState `json:"value"`
}
err := extract.Into(bytes.NewReader((r.(ResPage)).Body), &s)
err := extract.Into(bytes.NewReader((r.(CompliancePage)).Body), &s)
return s.Values, err
}

Expand Down
10 changes: 7 additions & 3 deletions openstack/rms/compliance/ListRules.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type ListRulesOpts struct {
// Specifies the number of records returned on each page during pagination query.
Limit *int `q:"limit"`
// Specifies the pagination parameter.
Marker string `q:"string"`
Marker string `q:"marker"`
}

func ListRules(client *golangsdk.ServiceClient, opts ListRulesOpts) ([]PolicyRule, error) {
Expand All @@ -31,7 +31,7 @@ func ListRules(client *golangsdk.ServiceClient, opts ListRulesOpts) ([]PolicyRul
Client: client,
InitialURL: client.ServiceURL(url.String()),
CreatePage: func(r pagination.NewPageResult) pagination.NewPage {
return ResPage{NewSinglePageBase: pagination.NewSinglePageBase{NewPageResult: r}}
return RulesPage{NewPageInfoBase: pagination.NewPageInfoBase{NewPageResult: r}}
},
}.NewAllPages()
if err != nil {
Expand All @@ -40,10 +40,14 @@ func ListRules(client *golangsdk.ServiceClient, opts ListRulesOpts) ([]PolicyRul
return ExtractRules(pages)
}

type RulesPage struct {
pagination.NewPageInfoBase
}

func ExtractRules(r pagination.NewPage) ([]PolicyRule, error) {
var s struct {
Rules []PolicyRule `json:"value"`
}
err := extract.Into(bytes.NewReader((r.(ResPage)).Body), &s)
err := extract.Into(bytes.NewReader((r.(RulesPage)).Body), &s)
return s.Rules, err
}
4 changes: 2 additions & 2 deletions openstack/rms/history/ListChangeRecords.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func ListAllRecords(client *golangsdk.ServiceClient, opts ListAllOpts) ([]Histor
Client: client,
InitialURL: client.ServiceURL(url.String()),
CreatePage: func(r pagination.NewPageResult) pagination.NewPage {
return ResPage{NewSinglePageBase: pagination.NewSinglePageBase{NewPageResult: r}}
return ResPage{NewPageInfoBase: pagination.NewPageInfoBase{NewPageResult: r}}
},
}.NewAllPages()
if err != nil {
Expand All @@ -45,7 +45,7 @@ func ListAllRecords(client *golangsdk.ServiceClient, opts ListAllOpts) ([]Histor
}

type ResPage struct {
pagination.NewSinglePageBase
pagination.NewPageInfoBase
}

func ExtractResources(r pagination.NewPage) ([]HistoryItem, error) {
Expand Down
2 changes: 1 addition & 1 deletion openstack/rms/query/ListAllResources.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func ListAllResources(client *golangsdk.ServiceClient, domainId string, opts Lis
Client: client,
InitialURL: client.ServiceURL(url.String()),
CreatePage: func(r pagination.NewPageResult) pagination.NewPage {
return ResPage{NewSinglePageBase: pagination.NewSinglePageBase{NewPageResult: r}}
return ResPage{NewPageInfoBase: pagination.NewPageInfoBase{NewPageResult: r}}
},
}.NewAllPages()
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion openstack/rms/query/ListAllResourcesTags.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func ListAllResourcesTags(client *golangsdk.ServiceClient, domainId string, opts
Client: client,
InitialURL: client.ServiceURL(url.String()),
CreatePage: func(r pagination.NewPageResult) pagination.NewPage {
return TagsPage{NewSinglePageBase: pagination.NewSinglePageBase{NewPageResult: r}}
return TagsPage{NewPageInfoBase: pagination.NewPageInfoBase{NewPageResult: r}}
},
}.NewAllPages()
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions openstack/rms/query/ListRecordeResourceTags.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func ListRecordedResourcesTags(client *golangsdk.ServiceClient, domainId string,
Client: client,
InitialURL: client.ServiceURL(url.String()),
CreatePage: func(r pagination.NewPageResult) pagination.NewPage {
return TagsPage{NewSinglePageBase: pagination.NewSinglePageBase{NewPageResult: r}}
return TagsPage{NewPageInfoBase: pagination.NewPageInfoBase{NewPageResult: r}}
},
}.NewAllPages()
if err != nil {
Expand All @@ -42,7 +42,7 @@ func ListRecordedResourcesTags(client *golangsdk.ServiceClient, domainId string,
}

type TagsPage struct {
pagination.NewSinglePageBase
pagination.NewPageInfoBase
}

func ExtractTags(r pagination.NewPage) ([]Tag, error) {
Expand Down
2 changes: 1 addition & 1 deletion openstack/rms/query/ListRecordedResources.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func ListRecordedResources(client *golangsdk.ServiceClient, domainId string, opt
Client: client,
InitialURL: client.ServiceURL(url.String()),
CreatePage: func(r pagination.NewPageResult) pagination.NewPage {
return ResPage{NewSinglePageBase: pagination.NewSinglePageBase{NewPageResult: r}}
return ResPage{NewPageInfoBase: pagination.NewPageInfoBase{NewPageResult: r}}
},
}.NewAllPages()
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions openstack/rms/query/ListSpecificType.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func ListSpecificType(client *golangsdk.ServiceClient, domainId, service, resour
Client: client,
InitialURL: client.ServiceURL(url.String()),
CreatePage: func(r pagination.NewPageResult) pagination.NewPage {
return ResPage{NewSinglePageBase: pagination.NewSinglePageBase{NewPageResult: r}}
return ResPage{NewPageInfoBase: pagination.NewPageInfoBase{NewPageResult: r}}
},
}.NewAllPages()
if err != nil {
Expand All @@ -42,7 +42,7 @@ func ListSpecificType(client *golangsdk.ServiceClient, domainId, service, resour
}

type ResPage struct {
pagination.NewSinglePageBase
pagination.NewPageInfoBase
}

func ExtractResources(r pagination.NewPage) ([]Resource, error) {
Expand Down
4 changes: 2 additions & 2 deletions openstack/rms/relations/ListRelations.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func ListRelations(client *golangsdk.ServiceClient, opts ListAllOpts) ([]Resourc
Client: client,
InitialURL: client.ServiceURL(url.String()),
CreatePage: func(r pagination.NewPageResult) pagination.NewPage {
return ResPage{NewSinglePageBase: pagination.NewSinglePageBase{NewPageResult: r}}
return ResPage{NewPageInfoBase: pagination.NewPageInfoBase{NewPageResult: r}}
},
}.NewAllPages()
if err != nil {
Expand All @@ -42,7 +42,7 @@ func ListRelations(client *golangsdk.ServiceClient, opts ListAllOpts) ([]Resourc
}

type ResPage struct {
pagination.NewSinglePageBase
pagination.NewPageInfoBase
}

func ExtractResources(r pagination.NewPage) ([]ResourceRelation, error) {
Expand Down
40 changes: 40 additions & 0 deletions pagination/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,43 @@ func NewPageWithInfo(r PageResult) PageWithInfo {
p.Owner = &p
return p
}

// NewPageInfoBase is a NewPage variant of PageWithInfo for the new pagination API.
// It extracts the next marker from `page_info.next_marker` in the response body.
type NewPageInfoBase struct {
NewPageResult
}

func (p NewPageInfoBase) NewNextPageURL() (string, error) {
var info pageInfo
err := extract.IntoStructPtr(bytes.NewReader(p.Body), &info, "page_info")
if err != nil {
return "", err
}
if info.NextMarker == "" {
return "", nil
}

currentURL := p.URL
q := currentURL.Query()
q.Set("marker", info.NextMarker)
currentURL.RawQuery = q.Encode()

return currentURL.String(), nil
}

func (p NewPageInfoBase) NewIsEmpty() (bool, error) {
body, err := p.NewGetBodyAsMap()
if err != nil {
return false, err
}
for k, v := range body {
if k == "page_info" {
continue
}
if items, ok := v.([]any); ok {
return len(items) == 0, nil
}
}
return true, nil
}
Loading
Loading