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

RMS: recorder & relation api #741

Merged
merged 1 commit into from
Oct 18, 2024
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
33 changes: 33 additions & 0 deletions acceptance/openstack/rms/v1/history_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package v1

import (
"os"
"testing"

"github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients"
"github.com/opentelekomcloud/gophertelekomcloud/acceptance/tools"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/rms/history"
th "github.com/opentelekomcloud/gophertelekomcloud/testhelper"
)

func TestHistoryList(t *testing.T) {
t.Skip("You are not authorized with rms:resources:list impossible to run within CI")
var resourceId string
if resourceId = os.Getenv("RESOURCE_ID"); resourceId == "" {
t.Skip("RESOURCE_ID is required for this test")
}
client, err := clients.NewRMSClient()
th.AssertNoErr(t, err)

listOpts := history.ListAllOpts{
DomainId: client.DomainID,
ResourceId: resourceId,
}

listHistory, err := history.ListAllRecords(
client,
listOpts,
)
th.AssertNoErr(t, err)
tools.AssertLengthGreaterThan(t, listHistory, 1)
}
55 changes: 55 additions & 0 deletions acceptance/openstack/rms/v1/recorder_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package v1

import (
"os"
"testing"

"github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/common/pointerto"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/rms/recorder"
th "github.com/opentelekomcloud/gophertelekomcloud/testhelper"
)

func TestRecorderLifecycle(t *testing.T) {
var agency, bucket string
if agency = os.Getenv("OS_AGENCY_NAME"); agency == "" {
t.Skip("OS_AGENCY_NAME is required for this test")
}
if bucket = os.Getenv("OS_BUCKET_NAME"); bucket == "" {
t.Skip("OS_BUCKET_NAME is required for this test")
}
client, err := clients.NewRMSClient()
th.AssertNoErr(t, err)

createOpts := recorder.UpdateOpts{
DomainId: client.DomainID,
Channel: recorder.ChannelConfigBody{
Obs: &recorder.TrackerObsConfigBody{
BucketName: bucket,
RegionId: client.RegionID,
},
},
Selector: recorder.SelectorConfigBody{
AllSupported: true,
ResourceTypes: []string{},
},
AgencyName: agency,
RetentionDays: pointerto.Int(2557),
}

err = recorder.UpdateRecorder(client, createOpts)
th.AssertNoErr(t, err)
t.Cleanup(func() {
err = recorder.DeleteRecorder(client, client.DomainID)
})
th.AssertNoErr(t, err)

resp, err := recorder.GetRecorder(client, client.DomainID)
th.AssertNoErr(t, err)

th.AssertEquals(t, createOpts.Channel.Obs.BucketName, resp.Channel.Obs.BucketName)
th.AssertEquals(t, createOpts.Channel.Obs.RegionId, resp.Channel.Obs.RegionId)
th.AssertEquals(t, createOpts.Selector.AllSupported, resp.Selector.AllSupported)
th.AssertEquals(t, createOpts.AgencyName, resp.AgencyName)
th.AssertEquals(t, *createOpts.RetentionDays, resp.RetentionPeriod)
}
34 changes: 34 additions & 0 deletions acceptance/openstack/rms/v1/relations_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package v1

import (
"os"
"testing"

"github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients"
"github.com/opentelekomcloud/gophertelekomcloud/acceptance/tools"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/rms/relations"
th "github.com/opentelekomcloud/gophertelekomcloud/testhelper"
)

func TestRelationsList(t *testing.T) {
t.Skip("You are not authorized with rms:resources:list impossible to run within CI")
var resourceId string
if resourceId = os.Getenv("RESOURCE_ID"); resourceId == "" {
t.Skip("RESOURCE_ID is required for this test")
}
client, err := clients.NewRMSClient()
th.AssertNoErr(t, err)

listOpts := relations.ListAllOpts{
DomainId: client.DomainID,
ResourceId: resourceId,
Direction: "out",
}

listRelations, err := relations.ListRelations(
client,
listOpts,
)
th.AssertNoErr(t, err)
tools.AssertLengthGreaterThan(t, listRelations, 1)
}
97 changes: 97 additions & 0 deletions openstack/rms/history/ListChangeRecords.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package history

import (
"bytes"

golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/extract"
"github.com/opentelekomcloud/gophertelekomcloud/pagination"
)

type ListAllOpts struct {
DomainId string `json:"-"`
ResourceId string `json:"-"`
// Specifies the maximum number of resources to return.
Limit *int `q:"limit"`
// Specifies the pagination parameter.
Marker string `q:"marker"`
// Specifies the start time of the query. If this parameter is not set, the earliest time is used by default.
EarlierTime *int64 `q:"earlier_time"`
// Specifies the end time of the query. If this parameter is not set, the current time is used by default.
LaterTime *int64 `q:"later_time"`
// Specifies the time sequence of the data to be returned. The default value is Reverse.
ChronologicalOrder *int64 `q:"chronological_order"`
}

func ListAllRecords(client *golangsdk.ServiceClient, opts ListAllOpts) ([]HistoryItem, error) {
// GET /v1/resource-manager/domains/{domain_id}/resources/{resource_id}/history
url, err := golangsdk.NewURLBuilder().
WithEndpoints("resource-manager", "domains", opts.DomainId, "resources", opts.ResourceId).
WithQueryParams(&opts).Build()
if err != nil {
return nil, err
}
pages, err := pagination.Pager{
Client: client,
InitialURL: client.ServiceURL(url.String()),
CreatePage: func(r pagination.NewPageResult) pagination.NewPage {
return ResPage{NewSinglePageBase: pagination.NewSinglePageBase{NewPageResult: r}}
},
}.NewAllPages()
if err != nil {
return nil, err
}
return ExtractResources(pages)
}

type ResPage struct {
pagination.NewSinglePageBase
}

func ExtractResources(r pagination.NewPage) ([]HistoryItem, error) {
var s struct {
Items []HistoryItem `json:"items"`
}
err := extract.Into(bytes.NewReader((r.(ResPage)).Body), &s)
return s.Items, err
}

type HistoryItem struct {
DomainId string `json:"domain_id"`
ResourceId string `json:"resource_id"`
ResourceType string `json:"resource_type"`
CaptureTime string `json:"capture_time"`
Status string `json:"status"`
Relations []Relations `json:"relations"`
Resource ResourceEntity `json:"resource"`
}

type Relations struct {
RelationType string `json:"relation_type"`
FromResourceType string `json:"from_resource_type"`
ToResourceType string `json:"to_resource_type"`
FromResourceId string `json:"from_resource_id"`
ToResourceId string `json:"to_resource_id"`
}

type ResourceEntity struct {
ID string `json:"id"`
Name string `json:"name"`
Provider string `json:"provider"`
Type string `json:"type"`
RegionID string `json:"region_id"`
ProjectID string `json:"project_id"`
ProjectName string `json:"project_name"`
EpID string `json:"ep_id"`
EpName string `json:"ep_name"`
Checksum string `json:"checksum"`
Created string `json:"created"`
Updated string `json:"updated"`
ProvisioningState string `json:"provisioning_state"`
State string `json:"state"`
Tags map[string]string `json:"tags"`
Properties map[string]interface{} `json:"properties"`
OSType string `json:"osType,omitempty"`
KeyName string `json:"keyName,omitempty"`
SchedulerHints interface{} `json:"schedulerHints,omitempty"`
}
13 changes: 13 additions & 0 deletions openstack/rms/recorder/DeleteRecorder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package recorder

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
)

func DeleteRecorder(client *golangsdk.ServiceClient, domainId string) (err error) {
// DELETE /v1/resource-manager/domains/{domain_id}/tracker-config
_, err = client.Delete(client.ServiceURL("resource-manager", "domains", domainId, "tracker-config"), &golangsdk.RequestOpts{
OkCodes: []int{200},
})
return
}
49 changes: 49 additions & 0 deletions openstack/rms/recorder/GetRecorder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package recorder

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/extract"
)

func GetRecorder(client *golangsdk.ServiceClient, domainId string) (*Recorder, error) {
// GET /v1/resource-manager/domains/{domain_id}/tracker-config
raw, err := client.Get(client.ServiceURL(
"resource-manager", "domains", domainId,
"tracker-config"), nil, nil)
if err != nil {
return nil, err
}

var res Recorder
err = extract.Into(raw.Body, &res)
return &res, err
}

type Recorder struct {
Channel ChannelConfigBody `json:"channel"`
Selector SelectorConfigBody `json:"selector"`
RetentionPeriod int `json:"retention_period_in_days"`
AgencyName string `json:"agency_name"`
}

type ChannelConfigBody struct {
Smn *TrackerSMNConfigBody `json:"smn,omitempty"`
Obs *TrackerObsConfigBody `json:"obs,omitempty"`
}

type TrackerSMNConfigBody struct {
RegionId string `json:"region_id"`
ProjectId string `json:"project_id"`
TopicUrn string `json:"topic_urn"`
}

type TrackerObsConfigBody struct {
BucketName string `json:"bucket_name"`
BucketPrefix *string `json:"bucket_prefix,omitempty"`
RegionId string `json:"region_id"`
}

type SelectorConfigBody struct {
AllSupported bool `json:"all_supported"`
ResourceTypes []string `json:"resource_types"`
}
32 changes: 32 additions & 0 deletions openstack/rms/recorder/UpdateRecorder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package recorder

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/build"
)

type UpdateOpts struct {
// Recorder domain id
DomainId string `json:"-"`
// Specifies configurations for the tracker channel.
Channel ChannelConfigBody `json:"channel" required:"true"`
// Specifies the selector.
Selector SelectorConfigBody `json:"selector" required:"true"`
// Number of days for data storage.
RetentionDays *int `json:"retention_period_in_days,omitempty"`
// Specifies the IAM agency name.
AgencyName string `json:"agency_name" required:"true"`
}

func UpdateRecorder(client *golangsdk.ServiceClient, opts UpdateOpts) error {
// PUT /v1/resource-manager/domains/{domain_id}/tracker-config
b, err := build.RequestBody(opts, "")
if err != nil {
return err
}

_, err = client.Put(client.ServiceURL("resource-manager", "domains", opts.DomainId, "tracker-config"), b, nil, &golangsdk.RequestOpts{
OkCodes: []int{200},
})
return err
}
62 changes: 62 additions & 0 deletions openstack/rms/relations/ListRelations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package relations

import (
"bytes"

golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/extract"
"github.com/opentelekomcloud/gophertelekomcloud/pagination"
)

type ListAllOpts struct {
DomainId string `json:"-"`
ResourceId string `json:"-"`
// Specifies the direction of a resource relationship.
Direction string `q:"direction"`
// Specifies the maximum number of resources to return.
Limit *int `q:"limit"`
// Specifies the pagination parameter.
Marker string `q:"marker"`
// Specifies the region ID.
}

func ListRelations(client *golangsdk.ServiceClient, opts ListAllOpts) ([]ResourceRelation, error) {
// GET /v1/resource-manager/domains/{domain_id}/all-resources/{resource_id}/relations
url, err := golangsdk.NewURLBuilder().
WithEndpoints("resource-manager", "domains", opts.DomainId, "all-resources", opts.ResourceId, "relations").
WithQueryParams(&opts).Build()
if err != nil {
return nil, err
}
pages, err := pagination.Pager{
Client: client,
InitialURL: client.ServiceURL(url.String()),
CreatePage: func(r pagination.NewPageResult) pagination.NewPage {
return ResPage{NewSinglePageBase: pagination.NewSinglePageBase{NewPageResult: r}}
},
}.NewAllPages()
if err != nil {
return nil, err
}
return ExtractResources(pages)
}

type ResPage struct {
pagination.NewSinglePageBase
}

func ExtractResources(r pagination.NewPage) ([]ResourceRelation, error) {
var s struct {
Resources []ResourceRelation `json:"relations"`
}
err := extract.Into(bytes.NewReader((r.(ResPage)).Body), &s)
return s.Resources, err
}

type ResourceRelation struct {
RelationType string `json:"relation_type"`
FromResourceType string `json:"from_resource_type"`
ToResourceType string `json:"to_resource_type"`
FromResourceId string `json:"from_resource_id"`
ToResourceId string `json:"to_resource_id"`
}