From 16530b08339ab6c2310ec013f46ba6eb55b7c465 Mon Sep 17 00:00:00 2001 From: jwierzbo Date: Sun, 24 Mar 2024 21:19:21 +0100 Subject: [PATCH] Set Licence API support --- v2/CHANGELOG.md | 1 + v2/arangodb/client_admin.go | 87 +-------------- v2/arangodb/client_admin_cluster.go | 128 +++++++++++++++++++++++ v2/arangodb/client_admin_license_impl.go | 41 +++++++- v2/arangodb/client_server_info.go | 6 ++ v2/tests/admin_license_test.go | 3 +- 6 files changed, 175 insertions(+), 91 deletions(-) create mode 100644 v2/arangodb/client_admin_cluster.go diff --git a/v2/CHANGELOG.md b/v2/CHANGELOG.md index 3aed694a..6b0fe6a7 100644 --- a/v2/CHANGELOG.md +++ b/v2/CHANGELOG.md @@ -18,6 +18,7 @@ - Wildcard analyzer support - Backup API support - Admin Cluster API support +- Set Licence API support ## [2.0.3](https://github.com/arangodb/go-driver/tree/v2.0.3) (2023-10-31) diff --git a/v2/arangodb/client_admin.go b/v2/arangodb/client_admin.go index 6e0f67b5..ebcb617e 100644 --- a/v2/arangodb/client_admin.go +++ b/v2/arangodb/client_admin.go @@ -40,40 +40,6 @@ type ClientAdmin interface { SetServerMode(ctx context.Context, mode ServerMode) error } -type ClientAdminCluster interface { - // Health returns the cluster configuration & health. Not available in single server deployments (403 Forbidden). - Health(ctx context.Context) (ClusterHealth, error) - - // DatabaseInventory the inventory of the cluster collections (with entire details) from a specific database. - DatabaseInventory(ctx context.Context, dbName string) (DatabaseInventory, error) - - // MoveShard moves a single shard of the given collection between `fromServer` and `toServer`. - MoveShard(ctx context.Context, col Collection, shard ShardID, fromServer, toServer ServerID) (string, error) - - // CleanOutServer triggers activities to clean out a DBServer. - CleanOutServer(ctx context.Context, serverID ServerID) (string, error) - - // ResignServer triggers activities to let a DBServer resign for all shards. - ResignServer(ctx context.Context, serverID ServerID) (string, error) - - // NumberOfServers returns the number of coordinators & dbServers in a clusters and the ID's of cleanedOut servers. - NumberOfServers(ctx context.Context) (NumberOfServersResponse, error) - - // IsCleanedOut checks if the dbServer with given ID has been cleaned out. - IsCleanedOut(ctx context.Context, serverID ServerID) (bool, error) - - // RemoveServer is a low-level option to remove a server from a cluster. - // This function is suitable for servers of type coordinator or dbServer. - // The use of `ClientServerAdmin.Shutdown` is highly recommended above this function. - RemoveServer(ctx context.Context, serverID ServerID) error -} - -type NumberOfServersResponse struct { - NoCoordinators int `json:"numberOfCoordinators,omitempty"` - NoDBServers int `json:"numberOfDBServers,omitempty"` - CleanedServerIDs []ServerID `json:"cleanedServers,omitempty"` -} - type ClientAdminLog interface { // GetLogLevels returns log levels for topics. GetLogLevels(ctx context.Context, opts *LogLevelsGetOptions) (LogLevels, error) @@ -85,55 +51,8 @@ type ClientAdminLog interface { type ClientAdminLicense interface { // GetLicense returns license of an ArangoDB deployment. GetLicense(ctx context.Context) (License, error) -} - -type DatabaseInventory struct { - Info DatabaseInfo `json:"properties,omitempty"` - Collections []InventoryCollection `json:"collections,omitempty"` - Views []InventoryView `json:"views,omitempty"` - State ServerStatus `json:"state,omitempty"` - Tick string `json:"tick,omitempty"` -} - -type InventoryCollection struct { - Parameters InventoryCollectionParameters `json:"parameters"` - Indexes []InventoryIndex `json:"indexes,omitempty"` - PlanVersion int64 `json:"planVersion,omitempty"` - IsReady bool `json:"isReady,omitempty"` - AllInSync bool `json:"allInSync,omitempty"` -} - -type InventoryCollectionParameters struct { - Deleted bool `json:"deleted,omitempty"` - Shards map[ShardID][]ServerID `json:"shards,omitempty"` - PlanID string `json:"planId,omitempty"` - - CollectionProperties -} - -type InventoryIndex struct { - ID string `json:"id,omitempty"` - Type string `json:"type,omitempty"` - Fields []string `json:"fields,omitempty"` - Unique bool `json:"unique"` - Sparse bool `json:"sparse"` - Deduplicate bool `json:"deduplicate"` - MinLength int `json:"minLength,omitempty"` - GeoJSON bool `json:"geoJson,omitempty"` - Name string `json:"name,omitempty"` - ExpireAfter int `json:"expireAfter,omitempty"` - Estimates bool `json:"estimates,omitempty"` - FieldValueTypes string `json:"fieldValueTypes,omitempty"` - CacheEnabled *bool `json:"cacheEnabled,omitempty"` -} - -type InventoryView struct { - Name string `json:"name,omitempty"` - Deleted bool `json:"deleted,omitempty"` - ID string `json:"id,omitempty"` - IsSystem bool `json:"isSystem,omitempty"` - PlanID string `json:"planId,omitempty"` - Type ViewType `json:"type,omitempty"` - ArangoSearchViewProperties + // SetLicense Set a new license for an Enterprise Edition instance. + // Can be called on single servers, Coordinators, and DB-Servers. + SetLicense(ctx context.Context, license string, force bool) error } diff --git a/v2/arangodb/client_admin_cluster.go b/v2/arangodb/client_admin_cluster.go new file mode 100644 index 00000000..36b51ffa --- /dev/null +++ b/v2/arangodb/client_admin_cluster.go @@ -0,0 +1,128 @@ +// +// DISCLAIMER +// +// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright holder is ArangoDB GmbH, Cologne, Germany +// + +package arangodb + +import "context" + +type ClientAdminCluster interface { + // Health returns the cluster configuration & health. Not available in single server deployments (403 Forbidden). + Health(ctx context.Context) (ClusterHealth, error) + + // DatabaseInventory the inventory of the cluster collections (with entire details) from a specific database. + DatabaseInventory(ctx context.Context, dbName string) (DatabaseInventory, error) + + // MoveShard moves a single shard of the given collection between `fromServer` and `toServer`. + MoveShard(ctx context.Context, col Collection, shard ShardID, fromServer, toServer ServerID) (string, error) + + // CleanOutServer triggers activities to clean out a DBServer. + CleanOutServer(ctx context.Context, serverID ServerID) (string, error) + + // ResignServer triggers activities to let a DBServer resign for all shards. + ResignServer(ctx context.Context, serverID ServerID) (string, error) + + // NumberOfServers returns the number of coordinators & dbServers in a clusters and the ID's of cleanedOut servers. + NumberOfServers(ctx context.Context) (NumberOfServersResponse, error) + + // IsCleanedOut checks if the dbServer with given ID has been cleaned out. + IsCleanedOut(ctx context.Context, serverID ServerID) (bool, error) + + // RemoveServer is a low-level option to remove a server from a cluster. + // This function is suitable for servers of type coordinator or dbServer. + // The use of `ClientServerAdmin.Shutdown` is highly recommended above this function. + RemoveServer(ctx context.Context, serverID ServerID) error +} + +type NumberOfServersResponse struct { + NoCoordinators int `json:"numberOfCoordinators,omitempty"` + NoDBServers int `json:"numberOfDBServers,omitempty"` + CleanedServerIDs []ServerID `json:"cleanedServers,omitempty"` +} + +type DatabaseInventory struct { + Info DatabaseInfo `json:"properties,omitempty"` + Collections []InventoryCollection `json:"collections,omitempty"` + Views []InventoryView `json:"views,omitempty"` + State ServerStatus `json:"state,omitempty"` + Tick string `json:"tick,omitempty"` +} + +type InventoryCollection struct { + Parameters InventoryCollectionParameters `json:"parameters"` + Indexes []InventoryIndex `json:"indexes,omitempty"` + PlanVersion int64 `json:"planVersion,omitempty"` + IsReady bool `json:"isReady,omitempty"` + AllInSync bool `json:"allInSync,omitempty"` +} + +type InventoryCollectionParameters struct { + Deleted bool `json:"deleted,omitempty"` + Shards map[ShardID][]ServerID `json:"shards,omitempty"` + PlanID string `json:"planId,omitempty"` + + CollectionProperties +} + +type InventoryIndex struct { + ID string `json:"id,omitempty"` + Type string `json:"type,omitempty"` + Fields []string `json:"fields,omitempty"` + Unique bool `json:"unique"` + Sparse bool `json:"sparse"` + Deduplicate bool `json:"deduplicate"` + MinLength int `json:"minLength,omitempty"` + GeoJSON bool `json:"geoJson,omitempty"` + Name string `json:"name,omitempty"` + ExpireAfter int `json:"expireAfter,omitempty"` + Estimates bool `json:"estimates,omitempty"` + FieldValueTypes string `json:"fieldValueTypes,omitempty"` + CacheEnabled *bool `json:"cacheEnabled,omitempty"` +} + +type InventoryView struct { + Name string `json:"name,omitempty"` + Deleted bool `json:"deleted,omitempty"` + ID string `json:"id,omitempty"` + IsSystem bool `json:"isSystem,omitempty"` + PlanID string `json:"planId,omitempty"` + Type ViewType `json:"type,omitempty"` + + ArangoSearchViewProperties +} + +// CollectionByName returns the InventoryCollection with given name. Return false if not found. +func (i DatabaseInventory) CollectionByName(name string) (InventoryCollection, bool) { + for _, c := range i.Collections { + if c.Parameters.Name == name { + return c, true + } + } + return InventoryCollection{}, false +} + +// ViewByName returns the InventoryView with given name. Return false if not found. +func (i DatabaseInventory) ViewByName(name string) (InventoryView, bool) { + for _, v := range i.Views { + if v.Name == name { + return v, true + } + } + return InventoryView{}, false +} diff --git a/v2/arangodb/client_admin_license_impl.go b/v2/arangodb/client_admin_license_impl.go index 2920ce34..88b26b2d 100644 --- a/v2/arangodb/client_admin_license_impl.go +++ b/v2/arangodb/client_admin_license_impl.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2023 ArangoDB GmbH, Cologne, Germany +// Copyright 2023-2024 ArangoDB GmbH, Cologne, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -42,27 +42,35 @@ type LicenseStatus string const ( // LicenseStatusGood - The license is valid for more than 2 weeks. LicenseStatusGood LicenseStatus = "good" + // LicenseStatusExpired - The license has expired. In this situation, no new Enterprise Edition features can be utilized. LicenseStatusExpired LicenseStatus = "expired" + // LicenseStatusExpiring - The license is valid for less than 2 weeks. LicenseStatusExpiring LicenseStatus = "expiring" + // LicenseStatusReadOnly - The license is expired over 2 weeks. The instance is now restricted to read-only mode. LicenseStatusReadOnly LicenseStatus = "read-only" ) // License describes license information. type License struct { - // Features describes properties of the license. + // Features describe properties of the license. Features LicenseFeatures `json:"features"` + // License is an encrypted license key in Base64 encoding. - License string `json:"license"` + License string `json:"license,omitempty"` + // Status is a status of a license. - Status LicenseStatus `json:"status"` + Status LicenseStatus `json:"status,omitempty"` + // Version is a version of a license. Version int `json:"version"` + + // Hash The hash value of the license. + Hash string `json:"hash,omitempty"` } -// GetLicense returns license of an ArangoDB deployment. func (c *clientAdmin) GetLicense(ctx context.Context) (License, error) { var response struct { shared.ResponseStruct `json:",inline"` @@ -80,3 +88,26 @@ func (c *clientAdmin) GetLicense(ctx context.Context) (License, error) { return License{}, response.AsArangoErrorWithCode(code) } } + +func (c *clientAdmin) SetLicense(ctx context.Context, license string, force bool) error { + var response struct { + shared.ResponseStruct `json:",inline"` + } + + var modifiers []connection.RequestModifier + if force { + modifiers = append(modifiers, connection.WithQuery("force", "true")) + } + + resp, err := connection.CallPut(ctx, c.client.connection, "_admin/license", &response, license, modifiers...) + if err != nil { + return errors.WithStack(err) + } + + switch code := resp.Code(); code { + case http.StatusCreated: + return nil + default: + return response.AsArangoErrorWithCode(code) + } +} diff --git a/v2/arangodb/client_server_info.go b/v2/arangodb/client_server_info.go index 842b670f..be7a1a44 100644 --- a/v2/arangodb/client_server_info.go +++ b/v2/arangodb/client_server_info.go @@ -30,10 +30,13 @@ import ( type ClientServerInfo interface { // Version returns version information from the connected database server. Version(ctx context.Context) (VersionInfo, error) + // VersionWithOptions returns version information from the connected database server. VersionWithOptions(ctx context.Context, opts *GetVersionOptions) (VersionInfo, error) + // ServerRole returns the role of the server that answers the request. ServerRole(ctx context.Context) (ServerRole, error) + // ServerID Gets the ID of this server in the cluster. // An error is returned when calling this to a server that is not part of a cluster. ServerID(ctx context.Context) (string, error) @@ -43,11 +46,14 @@ type ClientServerInfo interface { type VersionInfo struct { // This will always contain "arango" Server string `json:"server,omitempty"` + // The server version string. The string has the format "major.minor.sub". // Major and minor will be numeric, and sub may contain a number or a textual version. Version Version `json:"version,omitempty"` + // Type of license of the server License string `json:"license,omitempty"` + // Optional additional details. This is returned only if details were requested Details map[string]interface{} `json:"details,omitempty"` } diff --git a/v2/tests/admin_license_test.go b/v2/tests/admin_license_test.go index 47d89cb5..87837e70 100644 --- a/v2/tests/admin_license_test.go +++ b/v2/tests/admin_license_test.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2023 ArangoDB GmbH, Cologne, Germany +// Copyright 2023-2024 ArangoDB GmbH, Cologne, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -30,7 +30,6 @@ import ( "github.com/arangodb/go-driver/v2/arangodb" ) -// Test_License tests ArangoDB license. func Test_License(t *testing.T) { Wrap(t, func(t *testing.T, client arangodb.Client) { withContextT(t, defaultTestTimeout, func(ctx context.Context, t testing.TB) {