328 lines
8.6 KiB
Go
328 lines
8.6 KiB
Go
// Copyright (C) MongoDB, Inc. 2019-present.
|
|
//
|
|
// 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
|
|
|
|
package operation
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/event"
|
|
"go.mongodb.org/mongo-driver/mongo/description"
|
|
"go.mongodb.org/mongo-driver/mongo/readpref"
|
|
"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
|
|
"go.mongodb.org/mongo-driver/x/mongo/driver"
|
|
"go.mongodb.org/mongo-driver/x/mongo/driver/session"
|
|
)
|
|
|
|
// ListDatabases performs a listDatabases operation.
|
|
type ListDatabases struct {
|
|
filter bsoncore.Document
|
|
authorizedDatabases *bool
|
|
nameOnly *bool
|
|
session *session.Client
|
|
clock *session.ClusterClock
|
|
monitor *event.CommandMonitor
|
|
database string
|
|
deployment driver.Deployment
|
|
readPreference *readpref.ReadPref
|
|
retry *driver.RetryMode
|
|
selector description.ServerSelector
|
|
crypt driver.Crypt
|
|
serverAPI *driver.ServerAPIOptions
|
|
timeout *time.Duration
|
|
|
|
result ListDatabasesResult
|
|
}
|
|
|
|
// ListDatabasesResult represents a listDatabases result returned by the server.
|
|
type ListDatabasesResult struct {
|
|
// An array of documents, one document for each database
|
|
Databases []databaseRecord
|
|
// The sum of the size of all the database files on disk in bytes.
|
|
TotalSize int64
|
|
}
|
|
|
|
type databaseRecord struct {
|
|
Name string
|
|
SizeOnDisk int64 `bson:"sizeOnDisk"`
|
|
Empty bool
|
|
}
|
|
|
|
func buildListDatabasesResult(response bsoncore.Document) (ListDatabasesResult, error) {
|
|
elements, err := response.Elements()
|
|
if err != nil {
|
|
return ListDatabasesResult{}, err
|
|
}
|
|
ir := ListDatabasesResult{}
|
|
for _, element := range elements {
|
|
switch element.Key() {
|
|
case "totalSize":
|
|
var ok bool
|
|
ir.TotalSize, ok = element.Value().AsInt64OK()
|
|
if !ok {
|
|
return ir, fmt.Errorf("response field 'totalSize' is type int64, but received BSON type %s: %s", element.Value().Type, element.Value())
|
|
}
|
|
case "databases":
|
|
arr, ok := element.Value().ArrayOK()
|
|
if !ok {
|
|
return ir, fmt.Errorf("response field 'databases' is type array, but received BSON type %s", element.Value().Type)
|
|
}
|
|
|
|
var tmp bsoncore.Document
|
|
err := bson.Unmarshal(arr, &tmp)
|
|
if err != nil {
|
|
return ir, err
|
|
}
|
|
|
|
records, err := tmp.Elements()
|
|
if err != nil {
|
|
return ir, err
|
|
}
|
|
|
|
ir.Databases = make([]databaseRecord, len(records))
|
|
for i, val := range records {
|
|
valueDoc, ok := val.Value().DocumentOK()
|
|
if !ok {
|
|
return ir, fmt.Errorf("'databases' element is type document, but received BSON type %s", val.Value().Type)
|
|
}
|
|
|
|
elems, err := valueDoc.Elements()
|
|
if err != nil {
|
|
return ir, err
|
|
}
|
|
|
|
for _, elem := range elems {
|
|
switch elem.Key() {
|
|
case "name":
|
|
ir.Databases[i].Name, ok = elem.Value().StringValueOK()
|
|
if !ok {
|
|
return ir, fmt.Errorf("response field 'name' is type string, but received BSON type %s", elem.Value().Type)
|
|
}
|
|
case "sizeOnDisk":
|
|
ir.Databases[i].SizeOnDisk, ok = elem.Value().AsInt64OK()
|
|
if !ok {
|
|
return ir, fmt.Errorf("response field 'sizeOnDisk' is type int64, but received BSON type %s", elem.Value().Type)
|
|
}
|
|
case "empty":
|
|
ir.Databases[i].Empty, ok = elem.Value().BooleanOK()
|
|
if !ok {
|
|
return ir, fmt.Errorf("response field 'empty' is type bool, but received BSON type %s", elem.Value().Type)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ir, nil
|
|
}
|
|
|
|
// NewListDatabases constructs and returns a new ListDatabases.
|
|
func NewListDatabases(filter bsoncore.Document) *ListDatabases {
|
|
return &ListDatabases{
|
|
filter: filter,
|
|
}
|
|
}
|
|
|
|
// Result returns the result of executing this operation.
|
|
func (ld *ListDatabases) Result() ListDatabasesResult { return ld.result }
|
|
|
|
func (ld *ListDatabases) processResponse(info driver.ResponseInfo) error {
|
|
var err error
|
|
|
|
ld.result, err = buildListDatabasesResult(info.ServerResponse)
|
|
return err
|
|
|
|
}
|
|
|
|
// Execute runs this operations and returns an error if the operation did not execute successfully.
|
|
func (ld *ListDatabases) Execute(ctx context.Context) error {
|
|
if ld.deployment == nil {
|
|
return errors.New("the ListDatabases operation must have a Deployment set before Execute can be called")
|
|
}
|
|
|
|
return driver.Operation{
|
|
CommandFn: ld.command,
|
|
ProcessResponseFn: ld.processResponse,
|
|
|
|
Client: ld.session,
|
|
Clock: ld.clock,
|
|
CommandMonitor: ld.monitor,
|
|
Database: ld.database,
|
|
Deployment: ld.deployment,
|
|
ReadPreference: ld.readPreference,
|
|
RetryMode: ld.retry,
|
|
Type: driver.Read,
|
|
Selector: ld.selector,
|
|
Crypt: ld.crypt,
|
|
ServerAPI: ld.serverAPI,
|
|
Timeout: ld.timeout,
|
|
}.Execute(ctx)
|
|
|
|
}
|
|
|
|
func (ld *ListDatabases) command(dst []byte, desc description.SelectedServer) ([]byte, error) {
|
|
dst = bsoncore.AppendInt32Element(dst, "listDatabases", 1)
|
|
if ld.filter != nil {
|
|
|
|
dst = bsoncore.AppendDocumentElement(dst, "filter", ld.filter)
|
|
}
|
|
if ld.nameOnly != nil {
|
|
|
|
dst = bsoncore.AppendBooleanElement(dst, "nameOnly", *ld.nameOnly)
|
|
}
|
|
if ld.authorizedDatabases != nil {
|
|
|
|
dst = bsoncore.AppendBooleanElement(dst, "authorizedDatabases", *ld.authorizedDatabases)
|
|
}
|
|
|
|
return dst, nil
|
|
}
|
|
|
|
// Filter determines what results are returned from listDatabases.
|
|
func (ld *ListDatabases) Filter(filter bsoncore.Document) *ListDatabases {
|
|
if ld == nil {
|
|
ld = new(ListDatabases)
|
|
}
|
|
|
|
ld.filter = filter
|
|
return ld
|
|
}
|
|
|
|
// NameOnly specifies whether to only return database names.
|
|
func (ld *ListDatabases) NameOnly(nameOnly bool) *ListDatabases {
|
|
if ld == nil {
|
|
ld = new(ListDatabases)
|
|
}
|
|
|
|
ld.nameOnly = &nameOnly
|
|
return ld
|
|
}
|
|
|
|
// AuthorizedDatabases specifies whether to only return databases which the user is authorized to use."
|
|
func (ld *ListDatabases) AuthorizedDatabases(authorizedDatabases bool) *ListDatabases {
|
|
if ld == nil {
|
|
ld = new(ListDatabases)
|
|
}
|
|
|
|
ld.authorizedDatabases = &authorizedDatabases
|
|
return ld
|
|
}
|
|
|
|
// Session sets the session for this operation.
|
|
func (ld *ListDatabases) Session(session *session.Client) *ListDatabases {
|
|
if ld == nil {
|
|
ld = new(ListDatabases)
|
|
}
|
|
|
|
ld.session = session
|
|
return ld
|
|
}
|
|
|
|
// ClusterClock sets the cluster clock for this operation.
|
|
func (ld *ListDatabases) ClusterClock(clock *session.ClusterClock) *ListDatabases {
|
|
if ld == nil {
|
|
ld = new(ListDatabases)
|
|
}
|
|
|
|
ld.clock = clock
|
|
return ld
|
|
}
|
|
|
|
// CommandMonitor sets the monitor to use for APM events.
|
|
func (ld *ListDatabases) CommandMonitor(monitor *event.CommandMonitor) *ListDatabases {
|
|
if ld == nil {
|
|
ld = new(ListDatabases)
|
|
}
|
|
|
|
ld.monitor = monitor
|
|
return ld
|
|
}
|
|
|
|
// Database sets the database to run this operation against.
|
|
func (ld *ListDatabases) Database(database string) *ListDatabases {
|
|
if ld == nil {
|
|
ld = new(ListDatabases)
|
|
}
|
|
|
|
ld.database = database
|
|
return ld
|
|
}
|
|
|
|
// Deployment sets the deployment to use for this operation.
|
|
func (ld *ListDatabases) Deployment(deployment driver.Deployment) *ListDatabases {
|
|
if ld == nil {
|
|
ld = new(ListDatabases)
|
|
}
|
|
|
|
ld.deployment = deployment
|
|
return ld
|
|
}
|
|
|
|
// ReadPreference set the read preference used with this operation.
|
|
func (ld *ListDatabases) ReadPreference(readPreference *readpref.ReadPref) *ListDatabases {
|
|
if ld == nil {
|
|
ld = new(ListDatabases)
|
|
}
|
|
|
|
ld.readPreference = readPreference
|
|
return ld
|
|
}
|
|
|
|
// ServerSelector sets the selector used to retrieve a server.
|
|
func (ld *ListDatabases) ServerSelector(selector description.ServerSelector) *ListDatabases {
|
|
if ld == nil {
|
|
ld = new(ListDatabases)
|
|
}
|
|
|
|
ld.selector = selector
|
|
return ld
|
|
}
|
|
|
|
// Retry enables retryable mode for this operation. Retries are handled automatically in driver.Operation.Execute based
|
|
// on how the operation is set.
|
|
func (ld *ListDatabases) Retry(retry driver.RetryMode) *ListDatabases {
|
|
if ld == nil {
|
|
ld = new(ListDatabases)
|
|
}
|
|
|
|
ld.retry = &retry
|
|
return ld
|
|
}
|
|
|
|
// Crypt sets the Crypt object to use for automatic encryption and decryption.
|
|
func (ld *ListDatabases) Crypt(crypt driver.Crypt) *ListDatabases {
|
|
if ld == nil {
|
|
ld = new(ListDatabases)
|
|
}
|
|
|
|
ld.crypt = crypt
|
|
return ld
|
|
}
|
|
|
|
// ServerAPI sets the server API version for this operation.
|
|
func (ld *ListDatabases) ServerAPI(serverAPI *driver.ServerAPIOptions) *ListDatabases {
|
|
if ld == nil {
|
|
ld = new(ListDatabases)
|
|
}
|
|
|
|
ld.serverAPI = serverAPI
|
|
return ld
|
|
}
|
|
|
|
// Timeout sets the timeout for this operation.
|
|
func (ld *ListDatabases) Timeout(timeout *time.Duration) *ListDatabases {
|
|
if ld == nil {
|
|
ld = new(ListDatabases)
|
|
}
|
|
|
|
ld.timeout = timeout
|
|
return ld
|
|
}
|