arangodbaas

package module
v4.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 22, 2025 License: Apache-2.0 Imports: 13 Imported by: 0

README

Go build Coverage duplicated_lines_density vulnerabilities bugs code_smells

ArangoDB DBaaS Go Client

This module provides convenient way of interaction with ArangoDB databases provided by dbaas-aggregator. ArangoDB DBaaS Go Client supports multi-tenancy and can work with both service and tenant databases.

Install

To get ArangoDB DBaaS Go Client do:

    go get github.com/netcracker/qubership-core-lib-go-dbaas-arangodb-client

List of all released versions may be found here

Usage

At first, it's necessary to register security implemention - dummy or your own, the followning example shows registration of required services:

import (
	"github.com/netcracker/qubership-core-lib-go/v3/serviceloader"
	"github.com/netcracker/qubership-core-lib-go/v3/security"
)

func init() {
	serviceloader.Register(1, &security.DummyToken{})
}

Then the user should create DbaaSArangoDbClient. This is a base client, which allows working with tenant and service databases. To create instance of DbaaSArangoDbClient use NewClient(pool *dbaasbase.DbaaSPool) *DbaaSArangoDbClient.

Note that client has parameter pool. dbaasbase.DbaaSPool is a tool which stores all cached connections and create new ones. To find more info visit dbaasbase

Example of client creation:

pool := dbaasbase.NewDbaasPool()
client := arangodbaas.NewClient(pool)

Note:By default, ArangoDB DBaaS Go Client supports dbaas-aggregator as databases source. But there is a possibility for user to provide another sources. To do so use LogcalDbProvider from dbaasbase.

Next step is to create Database object. It just an interface which allows creating ArangoDB client. At this step user may choose which type of database he will work with: service or tenant.

  • To work with service databases use ServiceDatabase(params ...model.DbParams) Database
  • To work with tenant databases use TenantDatabase(params ...model.DbParams) Database

Each func has DbParams as parameter.

DbParams store information for database creation. Note that this parameter is optional, but if user doesn't pass Classifier, default one will be used. More about classifiers here

Name Description type
Classifier function which builds classifier from context. Classifier should be unique for each arango db. func(ctx context.Context) map[string]interface{}
BaseDbParams Specific parameters for operation with database. BaseDbParams

Example how to create an instance of Database.

 dbPool := dbaasbase.NewDbaasPool()
 client := arangodbaas.NewClient(dbPool)
 serviceDB := client.ServiceDatabase() // service Database creation 
 tenantDB := client.TenantDatabase() // tenant Database creation 

Database allows:

  • get ArangoDbClient, through which you can create Arango DB and get arangodb.Database for database operation. serviceDB and tenantDB instances should be singleton and it's enough to create them only once.
ArangoDbClient

ArangoDbClient is a special object, which allows getting arangodb.Database to establish connection and to operate with a database. ArangoDbClient is a singleton and should be created only once.

ArangoDbClient has method GetArangoDatabase(ctx context.Context, dbId string) (arangodb.Database, error) which will return arangodb.Database to work with the database. We strongly recommend not to store arangodb.Database as singleton and get new connection for every block of code. This is because the password in the database may be changed (by DBaaS or someone else) and then the connection will return an error. Every time the function arangoDbClient.GetArangoDatabase(ctx, dbId) is called, the password lifetime and correctness is checked. If necessary, the password is updated.

Note: classifier will be created with context and function from DbParams.

To create arangoDbClient use GetArangoDbClient(httpConfigs ...*connection.HttpConfiguration) (ArangoDbClient, error)

Parameters:

  • httpConfigs optional - user may pass desired *connection.HttpConfiguration or don't pass anything at all. Note that user doesn't have to set connection parameters with config, because these parameters will be received from dbaas-aggregator.
    ctx := ctxmanager.InitContext(context.Background(), propagateHeaders()) // preferred way
    // ctx := context.Background() // also possible for service client, but not recommended
    httpConfig := &connection.HttpConfiguration{}
    arangoDbClient, err := database.GetArangoDbClient(httpConfig) // with config
    dbId := "sample-db"
    arangoDb, err := arangoDbClient.GetArangoDatabase(ctx, dbId)

    collection, err := database.Collection(ctx, "collection-name")
    if err != nil { return err }
Get connection for existing database or create new one

Func GetConnectionProperties(ctx context.Context) (*model.ArangoConnProperties, error) at first will check if the desired database with arangodb type and classifier exists. If it exists, function will just return connection properties in the form of ArangoConnProperties. If database with arangodb type and classifier doesn't exist, such database will be created and function will return connection properties for a new created database.

Parameters:

  • ctx - context, enriched with some headers (See docs about context-propagation here). Context object can have request scope values from which can be used to build classifier, for example tenantId.
    ctx := ctxmanager.InitContext(context.Background(), propagateHeaders()) // preferred way
    // ctx := context.Background() // also possible for service client, but not recommended
    dbArangoConnection, err := database.GetConnectionProperties(ctx)
Find connection for existing database

Func FindConnectionProperties(ctx context.Context) (*model.ArangoConnProperties, error) returns connection properties in the form of ArangoConnProperties. Unlike GetConnectionProperties this function won't create database if it doesn't exist and just return nil value.

Parameters:

  • ctx - context, enriched with some headers. (See docs about context-propagation here). Context object can have request scope values from which can be used to build classifier, for example tenantId.
    ctx := ctxmanager.InitContext(context.Background(), propagateHeaders()) // preferred way
    // ctx := context.Background() // also possible for service client, but not recommended
    dbArangoConnection, err := database.FindConnectionProperties(ctx)
Arango multiusers

For specifying connection properties user role you should add this role in BaseDbParams structure:

params := model.DbParams{
        Classifier:   Classifier, //database classifier
        BaseDbParams: rest.BaseDbParams{Role: "admin"}, //for example "admin", "rw", "ro"
    }
dbPool := dbaasbase.NewDbaaSPool()
client := mongodbaas.NewClient(dbPool)
serviceDB := client.ServiceDatabase(params)
arangoClient, err := serviceDB.GetArangoDbClient()
dbId := "sample-db"
arangoDb, err := arangoClient.GetArangoDatabase(ctx, dbId)

Requests to DbaaS will contain the role you specify in this structure.

Classifier

Classifier and dbType should be unique combination for each database. Fields "tenantId" or "scope" must be into users' custom classifiers.

User can use default service or tenant classifier. It will be used if user doesn't specify Classifier in DbParams. This is recommended approach, and we don't recommend using custom classifier because it can lead to some problems. Use can be reasonable if you migrate to this module and before used custom and not default classifier.

Default service classifier looks like:

{
    "scope": "service",
    "microserviceName": "<ms-name>"
}

Default tenant classifier looks like

{
  "scope": "tenant",
  "tenantId": "<tenant-external-id>",
  "microserviceName": "<ms-name>"
}

Note, that if user doesn't set MICROSERVICE_NAME (or microservice.name) property, there will be panic during default classifier creation. Also, if there are no tenantId in tenantContext, panic will be thrown.

SSL/TLS support

This library supports work with secured connections to arangodb. Connection will be secured if TLS mode is enabled in arangodb-adapter.

For correct work with secured connections, the library requires having a truststore with certificate. It may be public cloud certificate, cert-manager's certificate or any type of certificates related to database. We do not recommend use self-signed certificates. Instead, use default NC-CA.

To start using TLS feature user has to enable it on the physical database (adapter's) side and add certificate to service truststore.

Physical database switching

To enable TLS support in physical database redeploy arangodb with mandatory parameters

tls.enabled=true;

In case of using cert-manager as certificates source add extra parameters

ISSUER_NAME=<cluster issuer name>;
tls.generateCerts.enabled=true;
tls.generateCerts.clusterIssuerName=<cluster issuer name>;

ClusterIssuerName identifies which Certificate Authority cert-manager will use to issue a certificate. It can be obtained from the person in charge of the cert-manager on the environment.

Quick example

Here we create ArangoDB tenant client, then get ArangoDbClient and execute a query.

application.yaml

  microservice.name=sample-microservice
package main

import (
	"context"
	"net/http"
	"github.com/netcracker/qubership-core-lib-go/v3/configloader"
	"github.com/netcracker/qubership-core-lib-go/v3/context-propagation/ctxmanager"
	"github.com/netcracker/qubership-core-lib-go/v3/logging"
	arangodbaas "github.com/netcracker/qubership-core-lib-go-dbaas-arangodb-client"
	dbaasbase "github.com/netcracker/qubership-core-lib-go-dbaas-base-client/v3"
	"github.com/netcracker/qubership-core-lib-go/v3/context-propagation/baseproviders/tenant"
	"github.com/arangodb/go-driver/v2/connection"
	"time"
)

func init() {
	configloader.InitWithSourcesArray(configloader.BasePropertySources())
	logger = logging.GetLogger("main")
	ctxmanager.Register([]ctxmanager.ContextProvider{tenant.TenantProvider{}})
}

func main() {

	// some context initialization
	ctx := ctxmanager.InitContext(context.Background(), map[string]interface{}{tenant.TenantHeader: "123"})

	// create tenant client
	dbaasPool := dbaasbase.NewDbaaSPool()
	dbaasArangoClient := arangodbaas.NewClient(dbaasPool)
	database := dbaasArangoClient.TenantDatabase()

	// create arangoClient
	httpConfig := connection.HttpConfiguration{
		Transport: &http.Transport{
			MaxIdleConns:          100,
			IdleConnTimeout:       90 * time.Second,
			TLSHandshakeTimeout:   10 * time.Second,
			ExpectContinueTimeout: 1 * time.Second,
		},
    }
	arangoClient, err := database.GetArangoDbClient(&httpConfig) // singleton for tenant databases. This object must be used to get connection in the entire application.
	if err != nil {
		logger.Error("Error during arango client creation")
	}

	// get database
	dbId := "sample-db"
	arangoDb, err := arangoClient.GetArangoDatabase(ctx, dbId)
	if err != nil {
		logger.Error("Error during arango database creation")
	}

	// sample DB operations
	collectionName := "sample-collection"
	found, err := arangoDb.CollectionExists(ctx, collectionName)
	if err != nil {
		logger.Error("Cannot check collection existence: %+v", err)
	}
	if !found {
		_, err = arangoDb.CreateCollection(ctx, collectionName, &arangodb.CreateCollectionProperties{})
		if err != nil {
			logger.Error("Cannot create collection: %+v", err)
		}
	}

	collection, err := arangoDb.Collection(ctx, collectionName)
	if err != nil {
		logger.Error("Cannot get collection: %+v", err)
	}
	document := Document{Text: "sample"}
	meta, err := collection.CreateDocument(ctx, document)
	if err != nil {
		logger.Error("Cannot create new document: %+v", err)
	}
	key := meta.Key

	var readDocument Document
	_, err = collection.ReadDocument(ctx, key, &readDocument)
	if err != nil {
		logger.Error("Cannot read document: %+v", err)
	}

	_, err = collection.DeleteDocument(ctx, key)
	if err != nil {
		logger.Error("Cannot remove document: %+v", err)
	}
}

type Document struct {
	Text string `json:"text"`
}

Documentation

Index

Constants

View Source
const (
	DbType = "arangodb"

	DbIdKey = "dbId"

	DefaultDbId = "default"

	TlsArangodbPort = 8530
)

Variables

This section is empty.

Functions

func ServiceClassifier

func ServiceClassifier(ctx context.Context) map[string]interface{}

func TenantClassifier

func TenantClassifier(ctx context.Context) map[string]interface{}

Types

type ArangoDbClient

type ArangoDbClient interface {
	GetArangoDatabase(ctx context.Context, dbId string) (arangodb.Database, error)
}

type ArangoDbClientImpl

type ArangoDbClientImpl struct {
	// contains filtered or unexported fields
}

func (*ArangoDbClientImpl) GetArangoDatabase

func (a *ArangoDbClientImpl) GetArangoDatabase(ctx context.Context, dbId string) (arangodb.Database, error)

type Database

type Database interface {
	GetArangoDbClient(httpConfigs ...*connection.HttpConfiguration) (ArangoDbClient, error)
	GetConnectionProperties(ctx context.Context) (*model.ArangoConnProperties, error)
	FindConnectionProperties(ctx context.Context) (*model.ArangoConnProperties, error)

	GetConnectionPropertiesWithDbId(ctx context.Context, dbId string) (*model.ArangoConnProperties, error)
	FindConnectionPropertiesWithDbId(ctx context.Context, dbId string) (*model.ArangoConnProperties, error)
}

type DbaaSArangoDbClient

type DbaaSArangoDbClient struct {
	// contains filtered or unexported fields
}

func NewClient

func NewClient(pool *dbaasbase.DbaaSPool) *DbaaSArangoDbClient

func (*DbaaSArangoDbClient) ServiceDatabase

func (d *DbaaSArangoDbClient) ServiceDatabase(params ...model.DbParams) Database

func (*DbaaSArangoDbClient) TenantDatabase

func (d *DbaaSArangoDbClient) TenantDatabase(params ...model.DbParams) Database

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL