From 7adc69dd73e9548a71f241888ffd3c0f5f8699e0 Mon Sep 17 00:00:00 2001 From: Lance52259 Date: Wed, 14 Apr 2021 09:54:40 +0800 Subject: [PATCH] feat: new CBR policy sdk supported --- openstack/cbr/v3/policies/requests.go | 133 ++++++++ openstack/cbr/v3/policies/results.go | 82 +++++ openstack/cbr/v3/policies/testing/fixtures.go | 313 ++++++++++++++++++ .../cbr/v3/policies/testing/requests_test.go | 67 ++++ openstack/cbr/v3/policies/urls.go | 11 + 5 files changed, 606 insertions(+) create mode 100644 openstack/cbr/v3/policies/requests.go create mode 100644 openstack/cbr/v3/policies/results.go create mode 100644 openstack/cbr/v3/policies/testing/fixtures.go create mode 100644 openstack/cbr/v3/policies/testing/requests_test.go create mode 100644 openstack/cbr/v3/policies/urls.go diff --git a/openstack/cbr/v3/policies/requests.go b/openstack/cbr/v3/policies/requests.go new file mode 100644 index 00000000..3514c8d6 --- /dev/null +++ b/openstack/cbr/v3/policies/requests.go @@ -0,0 +1,133 @@ +package policies + +import ( + "github.com/huaweicloud/golangsdk" + "github.com/huaweicloud/golangsdk/pagination" +) + +type CreateOpts struct { + Name string `json:"name" required:"true"` + OperationDefinition *PolicyODCreate `json:"operation_definition" required:"true"` + OperationType string `json:"operation_type" required:"true"` + Trigger *Trigger `json:"trigger" required:"true"` + Enabled *bool `json:"enabled,omitempty"` +} + +// PolicyODCreate is policy operation definition +type PolicyODCreate struct { + DailyBackups int `json:"day_backups,omitempty"` + WeekBackups int `json:"week_backups,omitempty"` + YearBackups int `json:"year_backups,omitempty"` + MonthBackups int `json:"month_backups,omitempty"` + MaxBackups int `json:"max_backups,omitempty"` + RetentionDurationDays int `json:"retention_duration_days,omitempty"` + Timezone string `json:"timezone,omitempty"` + EnableAcceleration bool `json:"enable_acceleration,omitempty"` + DestinationProjectID string `json:"destination_project_id,omitempty"` + DestinationRegion string `json:"destination_region,omitempty"` +} + +type TriggerProperties struct { + Pattern []string `json:"pattern" required:"true"` +} + +type Trigger struct { + Properties TriggerProperties `json:"properties" required:"true"` +} + +type CreateOptsBuilder interface { + ToPolicyCreateMap() (map[string]interface{}, error) +} + +func (opts CreateOpts) ToPolicyCreateMap() (map[string]interface{}, error) { + return golangsdk.BuildRequestBody(opts, "policy") +} + +//Create is a method by which to create function that create a CBR policy +func Create(client *golangsdk.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { + reqBody, err := opts.ToPolicyCreateMap() + if err != nil { + r.Err = err + return + } + _, err = client.Post(rootURL(client), reqBody, &r.Body, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + }) + r.Err = err + return +} + +type ListOpts struct { + OperationType string `q:"operation_type"` + VaultID string `q:"vault_id"` +} + +type ListOptsBuilder interface { + ToPolicyListQuery() (string, error) +} + +func (opts ListOpts) ToPolicyListQuery() (string, error) { + q, err := golangsdk.BuildQueryString(opts) + if err != nil { + return "", err + } + return q.String(), err +} + +//List is a method to obtain the specified CBR policy according to the vault ID or operation type. +//This method can also obtain all the CBR policies through the default parameter settings. +func List(client *golangsdk.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := rootURL(client) + if opts != nil { + query, err := opts.ToPolicyListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { + return PolicyPage{pagination.SinglePageBase(r)} + }) +} + +//Get is a method to obtain the specified CBR policy according to the policy ID. +func Get(client *golangsdk.ServiceClient, id string) (r GetResult) { + _, r.Err = client.Get(resourceURL(client, id), &r.Body, nil) + return +} + +type UpdateOpts struct { + Enabled *bool `json:"enabled,omitempty"` + Name string `json:"name,omitempty"` + OperationDefinition *PolicyODCreate `json:"operation_definition,omitempty"` + Trigger *Trigger `json:"trigger,omitempty"` +} + +type UpdateOptsBuilder interface { + ToPolicyUpdateMap() (map[string]interface{}, error) +} + +func (opts UpdateOpts) ToPolicyUpdateMap() (map[string]interface{}, error) { + return golangsdk.BuildRequestBody(opts, "policy") +} + +//Delete is a method to update an existing CBR policy +func Update(client *golangsdk.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) { + reqBody, err := opts.ToPolicyUpdateMap() + if err != nil { + r.Err = err + return + } + _, err = client.Put(resourceURL(client, id), reqBody, &r.Body, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + }) + r.Err = err + return +} + +//Delete is a method to delete an existing CBR policy +func Delete(client *golangsdk.ServiceClient, id string) (r DeleteResult) { + _, r.Err = client.Delete(resourceURL(client, id), nil) + return +} diff --git a/openstack/cbr/v3/policies/results.go b/openstack/cbr/v3/policies/results.go new file mode 100644 index 00000000..ddca350b --- /dev/null +++ b/openstack/cbr/v3/policies/results.go @@ -0,0 +1,82 @@ +package policies + +import ( + "fmt" + + "github.com/huaweicloud/golangsdk" + "github.com/huaweicloud/golangsdk/pagination" +) + +type commonResult struct { + golangsdk.Result +} + +type CreateResult struct { + commonResult +} + +type GetResult struct { + commonResult +} + +type UpdateResult struct { + commonResult +} + +type DeleteResult struct { + golangsdk.ErrResult +} + +type Policy struct { + ID string `json:"id"` + Name string `json:"name"` + Enabled bool `json:"enabled"` + OperationDefinition *PolicyODCreate `json:"operation_definition"` + OperationType string `json:"operation_type"` + Trigger *PolicyTriggerResp `json:"trigger"` + AssociatedVaults []PolicyAssociateVault `json:"associated_vaults"` +} + +type PolicyTriggerResp struct { + TriggerID string `json:"id"` + Name string `json:"name"` + Type string `json:"type"` + Properties PolicyTriggerPropertiesResp `json:"properties"` +} + +type PolicyTriggerPropertiesResp struct { + Pattern []string `json:"pattern"` + StartTime string `json:"start_time"` +} + +type PolicyAssociateVault struct { + VaultID string `json:"vault_id"` + DestinationVaultID string `json:"destination_vault_id"` +} + +func (r commonResult) Extract() (*Policy, error) { + var s struct { + Policy *Policy `json:"policy"` + } + if r.Err != nil { + return nil, r.Err + } + err := r.ExtractInto(&s) + if err != nil { + return nil, fmt.Errorf("error extracting policy from create response: %s", err) + } + return s.Policy, err +} + +type PolicyPage struct { + pagination.SinglePageBase +} + +func ExtractPolicies(r pagination.Page) ([]Policy, error) { + var s []Policy + err := r.(PolicyPage).Result.ExtractIntoSlicePtr(&s, "policies") + if err != nil { + return nil, err + } + return s, nil +} diff --git a/openstack/cbr/v3/policies/testing/fixtures.go b/openstack/cbr/v3/policies/testing/fixtures.go new file mode 100644 index 00000000..e52a9a00 --- /dev/null +++ b/openstack/cbr/v3/policies/testing/fixtures.go @@ -0,0 +1,313 @@ +package testing + +import ( + "fmt" + "net/http" + "testing" + + "github.com/huaweicloud/golangsdk/openstack/cbr/v3/policies" + th "github.com/huaweicloud/golangsdk/testhelper" + "github.com/huaweicloud/golangsdk/testhelper/client" +) + +const ( + expectedRequest = ` +{ + "policy" : { + "name" : "policy001", + "operation_definition" : { + "retention_duration_days" : 1, + "timezone" : "UTC+08:00" + }, + "operation_type" : "backup", + "trigger" : { + "properties" : { + "pattern" : [ + "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU;BYHOUR=14;BYMINUTE=00" + ] + } + } + } +}` + expectedCreateResponse = ` +{ + "policy" : { + "name" : "policy001", + "enabled" : true, + "trigger" : { + "properties" : { + "pattern" : [ "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU;BYHOUR=14;BYMINUTE=00" ], + "start_time" : "2019-05-08 06:57:05" + }, + "type" : "time", + "id" : "d67269a6-5369-42d7-8150-5254bd446328", + "name" : "default" + }, + "operation_definition" : { + "retention_duration_days" : 1, + "year_backups" : 0, + "day_backups" : 0, + "month_backups" : 0, + "week_backups" : 0, + "timezone" : "UTC+08:00" + }, + "operation_type" : "backup", + "id" : "cbb3ce6f-3332-4e7c-b98e-77290d8471ff" + } +}` + expectedUpdateResponse = ` +{ + "policy" : { + "name" : "policy001", + "enabled" : true, + "trigger" : { + "properties" : { + "pattern" : [ "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU;BYHOUR=14;BYMINUTE=00" ], + "start_time" : "2019-05-08 06:57:05" + }, + "type" : "time", + "id" : "d67269a6-5369-42d7-8150-5254bd446328", + "name" : "default" + }, + "operation_definition" : { + "max_backups" : 0, + "year_backups" : 0, + "day_backups" : 0, + "month_backups" : 0, + "week_backups" : 0, + "timezone" : "UTC+08:00", + "retention_duration_days": 1 + }, + "operation_type" : "backup", + "id" : "cbb3ce6f-3332-4e7c-b98e-77290d8471ff" + } +}` + expectedGetResponse = ` +{ + "policy" : { + "name" : "policy001", + "associated_vaults" : [ ], + "enabled" : true, + "trigger" : { + "properties" : { + "pattern" : [ "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU;BYHOUR=14;BYMINUTE=00" ], + "start_time" : "2019-05-08 06:57:05" + }, + "type" : "time", + "id" : "d67269a6-5369-42d7-8150-5254bd446328", + "name" : "default" + }, + "operation_definition" : { + "retention_duration_days" : 1, + "year_backups" : 0, + "day_backups" : 0, + "month_backups" : 0, + "week_backups" : 0, + "timezone" : "UTC+08:00" + }, + "operation_type" : "backup", + "id" : "cbb3ce6f-3332-4e7c-b98e-77290d8471ff" + } +}` + + expectedListResponse = ` +{ + "policies" : [ { + "name" : "policy001", + "associated_vaults" : [ ], + "enabled" : true, + "trigger" : { + "properties" : { + "pattern" : [ "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU;BYHOUR=14;BYMINUTE=00" ], + "start_time" : "2019-05-08 06:57:05" + }, + "type" : "time", + "id" : "d67269a6-5369-42d7-8150-5254bd446328", + "name" : "default" + }, + "operation_definition" : { + "retention_duration_days" : 1, + "year_backups" : 0, + "day_backups" : 0, + "month_backups" : 0, + "week_backups" : 0, + "timezone" : "UTC+08:00" + }, + "operation_type" : "backup", + "id" : "cbb3ce6f-3332-4e7c-b98e-77290d8471ff" + } ], + "count" : 10 +}` +) + +var ( + createOpts = &policies.CreateOpts{ + Name: "policy001", + OperationDefinition: &policies.PolicyODCreate{ + DailyBackups: 0, + WeekBackups: 0, + YearBackups: 0, + MonthBackups: 0, + MaxBackups: 0, + RetentionDurationDays: 1, + Timezone: "UTC+08:00", + }, + OperationType: "backup", + Trigger: &policies.Trigger{ + Properties: policies.TriggerProperties{ + Pattern: []string{ + "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU;BYHOUR=14;BYMINUTE=00", + }, + }, + }, + } + + expectedCreateResponseData = &policies.Policy{ + ID: "cbb3ce6f-3332-4e7c-b98e-77290d8471ff", + Name: "policy001", + Enabled: true, + OperationDefinition: &policies.PolicyODCreate{ + DailyBackups: 0, + WeekBackups: 0, + YearBackups: 0, + MonthBackups: 0, + MaxBackups: 0, + RetentionDurationDays: 1, + Timezone: "UTC+08:00", + }, + OperationType: "backup", + Trigger: &policies.PolicyTriggerResp{ + TriggerID: "d67269a6-5369-42d7-8150-5254bd446328", + Name: "default", + Type: "time", + Properties: policies.PolicyTriggerPropertiesResp{ + Pattern: []string{"FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU;BYHOUR=14;BYMINUTE=00"}, + StartTime: "2019-05-08 06:57:05", + }, + }, + } + updateEnabled = true + updateOpts = policies.UpdateOpts{ + Enabled: &updateEnabled, + Name: "policy001", + OperationDefinition: &policies.PolicyODCreate{ + DailyBackups: 0, + WeekBackups: 0, + YearBackups: 0, + MonthBackups: 0, + MaxBackups: 1, + RetentionDurationDays: 1, + Timezone: "UTC+08:00", + }, + Trigger: &policies.Trigger{ + Properties: policies.TriggerProperties{ + Pattern: []string{ + "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU;BYHOUR=14;BYMINUTE=00", + }, + }, + }, + } + + expectedGetResponseData = &policies.Policy{ + ID: "cbb3ce6f-3332-4e7c-b98e-77290d8471ff", + Name: "policy001", + AssociatedVaults: []policies.PolicyAssociateVault{}, + Enabled: true, + OperationDefinition: &policies.PolicyODCreate{ + DailyBackups: 0, + WeekBackups: 0, + YearBackups: 0, + MonthBackups: 0, + MaxBackups: 0, + RetentionDurationDays: 1, + Timezone: "UTC+08:00", + }, + OperationType: "backup", + Trigger: &policies.PolicyTriggerResp{ + TriggerID: "d67269a6-5369-42d7-8150-5254bd446328", + Name: "default", + Type: "time", + Properties: policies.PolicyTriggerPropertiesResp{ + Pattern: []string{"FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU;BYHOUR=14;BYMINUTE=00"}, + StartTime: "2019-05-08 06:57:05", + }, + }, + } + + expectedListResponseData = []policies.Policy{ + { + ID: "cbb3ce6f-3332-4e7c-b98e-77290d8471ff", + Name: "policy001", + AssociatedVaults: []policies.PolicyAssociateVault{}, + Enabled: true, + OperationDefinition: &policies.PolicyODCreate{ + DailyBackups: 0, + WeekBackups: 0, + YearBackups: 0, + MonthBackups: 0, + MaxBackups: 0, + RetentionDurationDays: 1, + Timezone: "UTC+08:00", + }, + OperationType: "backup", + Trigger: &policies.PolicyTriggerResp{ + TriggerID: "d67269a6-5369-42d7-8150-5254bd446328", + Name: "default", + Type: "time", + Properties: policies.PolicyTriggerPropertiesResp{ + Pattern: []string{"FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU;BYHOUR=14;BYMINUTE=00"}, + StartTime: "2019-05-08 06:57:05", + }, + }, + }, + } +) + +func handlePolicyCreation(t *testing.T) { + th.Mux.HandleFunc("/policies", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprint(w, expectedCreateResponse) + }) +} + +func handlePolicyDeletion(t *testing.T) { + th.Mux.HandleFunc("/policies/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "DELETE") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusNoContent) + }) +} + +func handlePolicyUpdate(t *testing.T) { + th.Mux.HandleFunc("/policies/cbb3ce6f-3332-4e7c-b98e-77290d8471ff", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "PUT") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprint(w, expectedUpdateResponse) + }) +} + +func handlePolicyGet(t *testing.T) { + th.Mux.HandleFunc("/policies/d32019d3-bc6e-4319-9c1d-6722fc136a22", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprint(w, expectedGetResponse) + }) +} + +func handlePolicyList(t *testing.T) { + th.Mux.HandleFunc("/policies", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "GET") + th.TestHeader(t, r, "X-Auth-Token", client.TokenID) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = fmt.Fprint(w, expectedListResponse) + }) +} diff --git a/openstack/cbr/v3/policies/testing/requests_test.go b/openstack/cbr/v3/policies/testing/requests_test.go new file mode 100644 index 00000000..028819f7 --- /dev/null +++ b/openstack/cbr/v3/policies/testing/requests_test.go @@ -0,0 +1,67 @@ +package testing + +import ( + "testing" + + "github.com/huaweicloud/golangsdk/openstack/cbr/v3/policies" + th "github.com/huaweicloud/golangsdk/testhelper" + "github.com/huaweicloud/golangsdk/testhelper/client" +) + +func TestCreateV3PolicyMarshall(t *testing.T) { + res, err := createOpts.ToPolicyCreateMap() + th.AssertNoErr(t, err) + th.AssertJSONEquals(t, expectedRequest, res) +} + +func TestCreateV3Policy(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + handlePolicyCreation(t) + + actual, err := policies.Create(client.ServiceClient(), createOpts).Extract() + th.AssertNoErr(t, err) + th.AssertDeepEquals(t, expectedCreateResponseData, actual) +} + +func TestDeleteV3Policy(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + handlePolicyDeletion(t) + + err := policies.Delete(client.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").ExtractErr() + th.AssertNoErr(t, err) +} + +func TestUpdateV3Policy(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + handlePolicyUpdate(t) + + updateId := "cbb3ce6f-3332-4e7c-b98e-77290d8471ff" + actual, err := policies.Update(client.ServiceClient(), updateId, updateOpts).Extract() + th.AssertNoErr(t, err) + th.AssertDeepEquals(t, expectedCreateResponseData, actual) +} + +func TestGetV3Policy(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + handlePolicyGet(t) + + actual, err := policies.Get(client.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").Extract() + th.AssertNoErr(t, err) + th.AssertDeepEquals(t, expectedGetResponseData, actual) +} + +func TestListV3Policy(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + handlePolicyList(t) + + pages, err := policies.List(client.ServiceClient(), policies.ListOpts{}).AllPages() + th.AssertNoErr(t, err) + actual, err := policies.ExtractPolicies(pages) + th.AssertNoErr(t, err) + th.AssertDeepEquals(t, expectedListResponseData, actual) +} diff --git a/openstack/cbr/v3/policies/urls.go b/openstack/cbr/v3/policies/urls.go new file mode 100644 index 00000000..59384513 --- /dev/null +++ b/openstack/cbr/v3/policies/urls.go @@ -0,0 +1,11 @@ +package policies + +import "github.com/huaweicloud/golangsdk" + +func rootURL(client *golangsdk.ServiceClient) string { + return client.ServiceURL("policies") +} + +func resourceURL(client *golangsdk.ServiceClient, id string) string { + return client.ServiceURL("policies", id) +}