From 89728597df4f5e8edf77d5a2e13323c3ca902b5a Mon Sep 17 00:00:00 2001 From: Andrei Ozerov Date: Sun, 10 Jun 2018 05:01:14 +0300 Subject: [PATCH] Gnocchi: implement archive policy Create method (#43) * Gnocchi: implement archive policy Create method Add support for creating Gnocchi archive policies. Add unit test and example in documentation. * Gnocchi: use "ArchivePolicyDefinitionOpts" name Use more broad name for archive policy definition options struct. * Gnocchi: fix some docs for create ap request * Archive Policies: add acc test for Create method Add acceptance test for the Create method and reusable helper CreateArchivePolicy method. * Gnocchi Archive Policies: fix inline comments Fix CreateOptsBuilder and CreateOpts inline comments. --- .../gnocchi/metric/v1/archivepolicies.go | 41 +++++++++++++ .../gnocchi/metric/v1/archivepolicies_test.go | 15 +++++ gnocchi/metric/v1/archivepolicies/doc.go | 26 ++++++++ gnocchi/metric/v1/archivepolicies/requests.go | 59 ++++++++++++++++++ gnocchi/metric/v1/archivepolicies/results.go | 6 ++ .../v1/archivepolicies/testing/fixtures.go | 48 +++++++++++++++ .../archivepolicies/testing/requests_test.go | 60 +++++++++++++++++++ gnocchi/metric/v1/archivepolicies/urls.go | 4 ++ 8 files changed, 259 insertions(+) create mode 100644 acceptance/gnocchi/metric/v1/archivepolicies.go diff --git a/acceptance/gnocchi/metric/v1/archivepolicies.go b/acceptance/gnocchi/metric/v1/archivepolicies.go new file mode 100644 index 00000000..a2634970 --- /dev/null +++ b/acceptance/gnocchi/metric/v1/archivepolicies.go @@ -0,0 +1,41 @@ +package v1 + +import ( + "testing" + + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/acceptance/tools" + "github.com/gophercloud/utils/gnocchi/metric/v1/archivepolicies" +) + +// CreateArchivePolicy will create a Gnocchi archive policy. An error will be returned if the +// archive policy could not be created. +func CreateArchivePolicy(t *testing.T, client *gophercloud.ServiceClient) (*archivepolicies.ArchivePolicy, error) { + policyName := tools.RandomString("TESTACCT-", 8) + createOpts := archivepolicies.CreateOpts{ + Name: policyName, + AggregationMethods: []string{ + "mean", + "sum", + }, + Definition: []archivepolicies.ArchivePolicyDefinitionOpts{ + { + Granularity: "1:00:00", + TimeSpan: "30 days, 0:00:00", + }, + { + Granularity: "24:00:00", + TimeSpan: "90 days, 0:00:00", + }, + }, + } + + t.Logf("Attempting to create a Gnocchi archive policy") + archivePolicy, err := archivepolicies.Create(client, createOpts).Extract() + if err != nil { + return nil, err + } + + t.Logf("Successfully created the Gnocchi archive policy.") + return archivePolicy, nil +} diff --git a/acceptance/gnocchi/metric/v1/archivepolicies_test.go b/acceptance/gnocchi/metric/v1/archivepolicies_test.go index dfb59985..a73f8a54 100644 --- a/acceptance/gnocchi/metric/v1/archivepolicies_test.go +++ b/acceptance/gnocchi/metric/v1/archivepolicies_test.go @@ -10,6 +10,21 @@ import ( "github.com/gophercloud/utils/gnocchi/metric/v1/archivepolicies" ) +func TestArchivePoliciesCRUD(t *testing.T) { + client, err := clients.NewGnocchiV1Client() + if err != nil { + t.Fatalf("Unable to create a Gnocchi client: %v", err) + } + + archivePolicy, err := CreateArchivePolicy(t, client) + if err != nil { + t.Fatalf("Unable to create a Gnocchi archive policy: %v", err) + } + // defer DeleteArchivePolicy(t, client, archivePolicy.ID) + + tools.PrintResource(t, archivePolicy) +} + func TestArchivePoliciesList(t *testing.T) { client, err := clients.NewGnocchiV1Client() if err != nil { diff --git a/gnocchi/metric/v1/archivepolicies/doc.go b/gnocchi/metric/v1/archivepolicies/doc.go index 2a8f477b..4a954c4f 100644 --- a/gnocchi/metric/v1/archivepolicies/doc.go +++ b/gnocchi/metric/v1/archivepolicies/doc.go @@ -25,5 +25,31 @@ Example of Getting an archive policy if err != nil { panic(err) } + +Example of Creating an archive policy + + createOpts := archivepolicies.CreateOpts{ + BackWindow: 31, + AggregationMethods: []string{ + "sum", + "mean", + "count", + }, + Definition: []archivepolicies.ArchivePolicyDefinitionOpts{ + { + Granularity: "1:00:00", + TimeSpan: "90 days, 0:00:00", + }, + { + Granularity: "1 day, 0:00:00", + TimeSpan: "100 days, 0:00:00", + }, + }, + Name: "test_policy", + } + archivePolicy, err := archivepolicies.Create(gnocchiClient, createOpts).Extract() + if err != nil { + panic(err) + } */ package archivepolicies diff --git a/gnocchi/metric/v1/archivepolicies/requests.go b/gnocchi/metric/v1/archivepolicies/requests.go index 33d6d02c..f14429c5 100644 --- a/gnocchi/metric/v1/archivepolicies/requests.go +++ b/gnocchi/metric/v1/archivepolicies/requests.go @@ -17,3 +17,62 @@ func Get(c *gophercloud.ServiceClient, archivePolicyName string) (r GetResult) { _, r.Err = c.Get(getURL(c, archivePolicyName), &r.Body, nil) return } + +// CreateOptsBuilder allows extensions to add additional parameters to the Create request. +type CreateOptsBuilder interface { + ToArchivePolicyCreateMap() (map[string]interface{}, error) +} + +// CreateOpts specifies parameters of a new Archive Policy. +type CreateOpts struct { + // AggregationMethods is a list of functions used to aggregate + // multiple measures into an aggregate. + AggregationMethods []string `json:"aggregation_methods,omitempty"` + + // BackWindow configures number of coarsest periods to keep. + // It allows to process measures that are older + // than the last timestamp period boundary. + BackWindow int `json:"back_window,omitempty"` + + // Definition is a list of parameters that configures + // archive policy precision and timespan. + Definition []ArchivePolicyDefinitionOpts `json:"definition"` + + // Name is a name of an archive policy. + Name string `json:"name"` +} + +// ArchivePolicyDefinitionOpts represents definition of how metrics of new or +// updated Archive Policy will be saved with the selected archive policy. +// It configures precision and timespan. +type ArchivePolicyDefinitionOpts struct { + // Granularity is the level of precision that must be kept when aggregating data. + Granularity string `json:"granularity"` + + // Points is a given aggregates or samples in the lifespan of a time series. + // Time series is a list of aggregates ordered by time. + // It can be omitted to allow Gnocchi server to calculate it automatically. + Points *int `json:"points,omitempty"` + + // TimeSpan is the time period for which a metric keeps its aggregates. + TimeSpan string `json:"timespan"` +} + +// ToArchivePolicyCreateMap constructs a request body from CreateOpts. +func (opts CreateOpts) ToArchivePolicyCreateMap() (map[string]interface{}, error) { + return gophercloud.BuildRequestBody(opts, "") +} + +// Create requests the creation of a new Gnocchi archive policy on the server. +func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { + b, err := opts.ToArchivePolicyCreateMap() + if err != nil { + r.Err = err + return + } + _, r.Err = client.Post(createURL(client), b, &r.Body, &gophercloud.RequestOpts{ + OkCodes: []int{201}, + }) + + return +} diff --git a/gnocchi/metric/v1/archivepolicies/results.go b/gnocchi/metric/v1/archivepolicies/results.go index 015e0bd0..a7fe2244 100644 --- a/gnocchi/metric/v1/archivepolicies/results.go +++ b/gnocchi/metric/v1/archivepolicies/results.go @@ -22,6 +22,12 @@ type GetResult struct { commonResult } +// CreateResult represents the result of a create operation. Call its Extract +// method to interpret it as a Gnocchi archive policy. +type CreateResult struct { + commonResult +} + // ArchivePolicy represents a Gnocchi archive policy. // Archive policy is an aggregate storage policy attached to a metric. // It determines how long aggregates will be kept in a metric and how they will be aggregated. diff --git a/gnocchi/metric/v1/archivepolicies/testing/fixtures.go b/gnocchi/metric/v1/archivepolicies/testing/fixtures.go index de0faa90..11a44d8e 100644 --- a/gnocchi/metric/v1/archivepolicies/testing/fixtures.go +++ b/gnocchi/metric/v1/archivepolicies/testing/fixtures.go @@ -126,3 +126,51 @@ const ArchivePolicyGetResult = ` "name": "test_policy" } ` + +// ArchivePolicyCreateRequest represents a raw create request. +const ArchivePolicyCreateRequest = ` +{ + "aggregation_methods": [ + "sum", + "mean", + "count" + ], + "back_window": 31, + "definition": [ + { + "granularity": "1:00:00", + "timespan": "90 days, 0:00:00" + }, + { + "granularity": "1 day, 0:00:00", + "timespan": "100 days, 0:00:00" + } + ], + "name": "test_policy" +} +` + +// ArchivePolicyCreateResponse represents a raw server response from a server to a create request. +const ArchivePolicyCreateResponse = ` +{ + "aggregation_methods": [ + "sum", + "mean", + "count" + ], + "back_window": 31, + "definition": [ + { + "granularity": "1:00:00", + "points": 2160, + "timespan": "90 days, 0:00:00" + }, + { + "granularity": "1 day, 0:00:00", + "points": 100, + "timespan": "100 days, 0:00:00" + } + ], + "name": "test_policy" +} +` diff --git a/gnocchi/metric/v1/archivepolicies/testing/requests_test.go b/gnocchi/metric/v1/archivepolicies/testing/requests_test.go index 794b6a81..584ba033 100644 --- a/gnocchi/metric/v1/archivepolicies/testing/requests_test.go +++ b/gnocchi/metric/v1/archivepolicies/testing/requests_test.go @@ -101,3 +101,63 @@ func TestGetArchivePolicy(t *testing.T) { }) th.AssertEquals(t, s.Name, "test_policy") } + +func TestCreate(t *testing.T) { + th.SetupHTTP() + defer th.TeardownHTTP() + + th.Mux.HandleFunc("/v1/archive_policy", func(w http.ResponseWriter, r *http.Request) { + th.TestMethod(t, r, "POST") + th.TestHeader(t, r, "X-Auth-Token", fake.TokenID) + th.TestHeader(t, r, "Content-Type", "application/json") + th.TestHeader(t, r, "Accept", "application/json") + th.TestJSONRequest(t, r, ArchivePolicyCreateRequest) + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + + fmt.Fprintf(w, ArchivePolicyCreateResponse) + }) + + opts := archivepolicies.CreateOpts{ + BackWindow: 31, + AggregationMethods: []string{ + "sum", + "mean", + "count", + }, + Definition: []archivepolicies.ArchivePolicyDefinitionOpts{ + { + Granularity: "1:00:00", + TimeSpan: "90 days, 0:00:00", + }, + { + Granularity: "1 day, 0:00:00", + TimeSpan: "100 days, 0:00:00", + }, + }, + Name: "test_policy", + } + s, err := archivepolicies.Create(fake.ServiceClient(), opts).Extract() + th.AssertNoErr(t, err) + + th.AssertDeepEquals(t, s.AggregationMethods, []string{ + "sum", + "mean", + "count", + }) + th.AssertEquals(t, s.BackWindow, 31) + th.AssertDeepEquals(t, s.Definition, []archivepolicies.ArchivePolicyDefinition{ + { + Granularity: "1:00:00", + Points: 2160, + TimeSpan: "90 days, 0:00:00", + }, + { + Granularity: "1 day, 0:00:00", + Points: 100, + TimeSpan: "100 days, 0:00:00", + }, + }) + th.AssertEquals(t, s.Name, "test_policy") +} diff --git a/gnocchi/metric/v1/archivepolicies/urls.go b/gnocchi/metric/v1/archivepolicies/urls.go index c940cf64..c2f2337b 100644 --- a/gnocchi/metric/v1/archivepolicies/urls.go +++ b/gnocchi/metric/v1/archivepolicies/urls.go @@ -19,3 +19,7 @@ func listURL(c *gophercloud.ServiceClient) string { func getURL(c *gophercloud.ServiceClient, archivePolicyName string) string { return resourceURL(c, archivePolicyName) } + +func createURL(c *gophercloud.ServiceClient) string { + return rootURL(c) +}