From 88edbb831d624086db519b856c5d95e846e182c2 Mon Sep 17 00:00:00 2001 From: Michael Minichino <36450266+mminichino@users.noreply.github.com> Date: Mon, 29 Jan 2024 20:04:14 -0600 Subject: [PATCH] Version 2.2.7 --- .bumpversion.cfg | 2 +- README.md | 2 +- VERSION | 2 +- cbcmgr/__init__.py | 2 +- cbcmgr/cb_bucket.py | 24 +++++++++--------- cbcmgr/cb_connect_lite.py | 32 +++++++++++++++--------- cbcmgr/cb_connect_lite_a.py | 49 +++++++++++++++++++++++++------------ cbcmgr/cb_management.py | 15 ++++++++++-- cbcmgr/cb_operation_a.py | 2 +- cbcmgr/restmgr.py | 5 ++-- tests/test_6.py | 7 ++++++ 11 files changed, 95 insertions(+), 47 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index e76fe83..f355261 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 2.2.6 +current_version = 2.2.7 commit = False tag = False message = 'Version {new_version}' diff --git a/README.md b/README.md index 5b68d57..fa6a4c2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# cb-util 2.2.6 +# cb-util 2.2.7 ## Couchbase Utilities Couchbase connection manager. Simplifies connecting to a Couchbase cluster and performing data and management operations. diff --git a/VERSION b/VERSION index bda8fbe..5bc1cc4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.6 +2.2.7 diff --git a/cbcmgr/__init__.py b/cbcmgr/__init__.py index 7b32372..d8ffe85 100644 --- a/cbcmgr/__init__.py +++ b/cbcmgr/__init__.py @@ -2,7 +2,7 @@ from pkg_resources import parse_version _ROOT = os.path.abspath(os.path.dirname(__file__)) -__version__ = "2.2.6" +__version__ = "2.2.7" VERSION = parse_version(__version__) diff --git a/cbcmgr/cb_bucket.py b/cbcmgr/cb_bucket.py index e6a9839..5277db1 100644 --- a/cbcmgr/cb_bucket.py +++ b/cbcmgr/cb_bucket.py @@ -89,17 +89,17 @@ class Bucket: @classmethod def from_dict(cls, values: dict): return cls( - values.get('flush_enabled'), - values.get('num_replicas'), - values.get('ram_quota_mb'), - values.get('replica_index'), - BucketType(values.get('bucket_type')), - values.get('max_ttl'), - timedelta(values.get('max_expiry')), - CompressionMode(values.get('compression_mode')), - ConflictResolutionType(values.get('conflict_resolution_type')), - EvictionPolicyType(values.get('eviction_policy')), + values.get('flush_enabled', False), + values.get('num_replicas', 1), + values.get('ram_quota_mb', 128), + values.get('replica_index', False), + BucketType(values.get('bucket_type', "membase")), + values.get('max_ttl', 0), + timedelta(values.get('max_expiry', 0)), + CompressionMode(values.get('compression_mode', "passive")), + ConflictResolutionType(values.get('conflict_resolution_type', "seqno")), + EvictionPolicyType(values.get('eviction_policy', "valueOnly")), values.get('name'), - DurabilityLevel(values.get('minimum_durability_level')), - StorageBackend(values.get('storage_backend')), + DurabilityLevel(values.get('minimum_durability_level', 0)), + StorageBackend(values.get('storage_backend', "couchstore")), ) diff --git a/cbcmgr/cb_connect_lite.py b/cbcmgr/cb_connect_lite.py index 00ed952..df62a9b 100644 --- a/cbcmgr/cb_connect_lite.py +++ b/cbcmgr/cb_connect_lite.py @@ -10,7 +10,6 @@ from .httpsessionmgr import APISession import logging import hashlib -import attr from datetime import timedelta from typing import Union, Dict, Any, List from couchbase.cluster import Cluster @@ -19,7 +18,7 @@ from couchbase.collection import Collection from couchbase.options import QueryOptions from couchbase.management.users import Role, User, Group -from couchbase.management.buckets import CreateBucketSettings, BucketType, StorageBackend +from couchbase.management.buckets import CreateBucketSettings, BucketType, EvictionPolicyType, CompressionMode, ConflictResolutionType from couchbase.management.collections import CollectionSpec from couchbase.management.options import CreateQueryIndexOptions, CreatePrimaryQueryIndexOptions, WatchQueryIndexOptions from couchbase.exceptions import (BucketNotFoundException, ScopeNotFoundException, CollectionNotFoundException, BucketAlreadyExistsException, ScopeAlreadyExistsException, @@ -60,18 +59,18 @@ def create_bucket(self, cluster: Cluster, name: str, quota: int = 256, replicas: raise TypeError("name can not be None") if mode == BucketMode.DEFAULT: - b_type = BucketType.COUCHBASE - b_stor = StorageBackend.COUCHSTORE + b_type = "membase" + b_stor = "couchstore" elif mode == BucketMode.CACHE: - b_type = BucketType.EPHEMERAL - b_stor = StorageBackend.COUCHSTORE + b_type = "ephemeral" + b_stor = "couchstore" else: - b_type = BucketType.COUCHBASE - b_stor = StorageBackend.MAGMA + b_type = "membase" + b_stor = "magma" - logger.debug(f"creating bucket {name} type {b_type.name} storage {b_stor.name} replicas {replicas} quota {quota}") + logger.debug(f"creating bucket {name} type {b_type} storage {b_stor} replicas {replicas} quota {quota}") - bucket_opts = CouchbaseBucket(**dict( + bucket_opts = CouchbaseBucket.from_dict(dict( name=name, ram_quota_mb=quota, bucket_type=b_type, @@ -96,7 +95,18 @@ def create_bucket(self, cluster: Cluster, name: str, quota: int = 256, replicas: try: bm = cluster.buckets() # noinspection PyTypeChecker - bm.create_bucket(CreateBucketSettings(**attr.asdict(bucket_opts))) + bm.create_bucket(CreateBucketSettings( + name=bucket_opts.name, + flush_enabled=bucket_opts.flush_enabled, + replica_index=bucket_opts.replica_index, + ram_quota_mb=bucket_opts.ram_quota_mb, + num_replicas=bucket_opts.num_replicas, + bucket_type=BucketType(bucket_opts.bucket_type.value), + eviction_policy=EvictionPolicyType(bucket_opts.eviction_policy.value), + max_ttl=bucket_opts.max_ttl, + compression_mode=CompressionMode(bucket_opts.compression_mode.value), + conflict_resolution_type=ConflictResolutionType(bucket_opts.conflict_resolution_type.value) + )) except BucketAlreadyExistsException: pass diff --git a/cbcmgr/cb_connect_lite_a.py b/cbcmgr/cb_connect_lite_a.py index 6d40ce4..82a48ab 100644 --- a/cbcmgr/cb_connect_lite_a.py +++ b/cbcmgr/cb_connect_lite_a.py @@ -1,11 +1,12 @@ ## ## -import asyncio +import asyncio from .exceptions import (IndexInternalError, CollectionCountError, BucketStatsError) from .retry import retry from .cb_session import CBSession, BucketMode from .httpsessionmgr import APISession +from .cb_bucket import Bucket as CouchbaseBucket import logging import hashlib from datetime import timedelta @@ -14,7 +15,7 @@ from acouchbase.bucket import AsyncBucket from acouchbase.scope import AsyncScope from acouchbase.collection import AsyncCollection -from couchbase.management.buckets import CreateBucketSettings, BucketType, StorageBackend +from couchbase.management.buckets import CreateBucketSettings, BucketType, EvictionPolicyType, CompressionMode, ConflictResolutionType from couchbase.management.collections import CollectionSpec from couchbase.management.options import CreateQueryIndexOptions, CreatePrimaryQueryIndexOptions, WatchQueryIndexOptions from couchbase.exceptions import (BucketNotFoundException, ScopeNotFoundException, CollectionNotFoundException, BucketAlreadyExistsException, ScopeAlreadyExistsException, @@ -40,29 +41,47 @@ async def get_bucket(self, cluster: AsyncCluster, name: str) -> AsyncBucket: return bucket @retry() - async def create_bucket(self, cluster: AsyncCluster, name: str, quota: int = 256, replicas: int = 0, mode: BucketMode = BucketMode.DEFAULT): + async def create_bucket(self, cluster: AsyncCluster, name: str, quota: int = 256, replicas: int = 0, max_ttl: int = 0, flush: bool = False, + mode: BucketMode = BucketMode.DEFAULT): if name is None: raise TypeError("name can not be None") if mode == BucketMode.DEFAULT: - b_type = BucketType.COUCHBASE - b_stor = StorageBackend.COUCHSTORE + b_type = "membase" + b_stor = "couchstore" elif mode == BucketMode.CACHE: - b_type = BucketType.EPHEMERAL - b_stor = StorageBackend.COUCHSTORE + b_type = "ephemeral" + b_stor = "couchstore" else: - b_type = BucketType.COUCHBASE - b_stor = StorageBackend.MAGMA + b_type = "membase" + b_stor = "magma" + + logger.debug(f"creating bucket {name} type {b_type} storage {b_stor} replicas {replicas} quota {quota}") - logger.debug(f"creating bucket {name} type {b_type.name} storage {b_stor.name} replicas {replicas} quota {quota}") + bucket_opts = CouchbaseBucket.from_dict(dict( + name=name, + ram_quota_mb=quota, + bucket_type=b_type, + storage_backend=b_stor, + num_replicas=replicas, + max_ttl=max_ttl, + flush_enabled=flush + )) try: bm = cluster.buckets() - await bm.create_bucket(CreateBucketSettings(name=name, - bucket_type=b_type, - storage_backend=b_stor, - num_replicas=replicas, - ram_quota_mb=quota)) + await bm.create_bucket(CreateBucketSettings( + name=bucket_opts.name, + flush_enabled=bucket_opts.flush_enabled, + replica_index=bucket_opts.replica_index, + ram_quota_mb=bucket_opts.ram_quota_mb, + num_replicas=bucket_opts.num_replicas, + bucket_type=BucketType(bucket_opts.bucket_type.value), + eviction_policy=EvictionPolicyType(bucket_opts.eviction_policy.value), + max_ttl=bucket_opts.max_ttl, + compression_mode=CompressionMode(bucket_opts.compression_mode.value), + conflict_resolution_type=ConflictResolutionType(bucket_opts.conflict_resolution_type.value) + )) except BucketAlreadyExistsException: pass diff --git a/cbcmgr/cb_management.py b/cbcmgr/cb_management.py index 360a175..1cf913d 100644 --- a/cbcmgr/cb_management.py +++ b/cbcmgr/cb_management.py @@ -13,7 +13,6 @@ from .cb_capella import Capella from .httpsessionmgr import APISession from datetime import timedelta -import attr import hashlib import logging import json @@ -30,6 +29,7 @@ from couchbase.management.queries import (CreateQueryIndexOptions, CreatePrimaryQueryIndexOptions, WatchQueryIndexOptions, DropPrimaryQueryIndexOptions, DropQueryIndexOptions) from couchbase.management.options import CreateBucketOptions, CreateScopeOptions, CreateCollectionOptions, GetAllQueryIndexOptions from couchbase.options import WaitUntilReadyOptions, UpsertOptions +from couchbase.management.logic.buckets_logic import BucketType, CompressionMode, ConflictResolutionType, EvictionPolicyType logger = logging.getLogger('cbutil.manager') logger.addHandler(logging.NullHandler()) @@ -79,7 +79,18 @@ def create_bucket(self, bucket: Bucket): try: bm = self._cluster.buckets() # noinspection PyTypeChecker - bm.create_bucket(CreateBucketSettings(**attr.asdict(bucket)), CreateBucketOptions(timeout=timedelta(seconds=25))) + bm.create_bucket(CreateBucketSettings( + name=bucket.name, + flush_enabled=bucket.flush_enabled, + replica_index=bucket.replica_index, + ram_quota_mb=bucket.ram_quota_mb, + num_replicas=bucket.num_replicas, + bucket_type=BucketType(bucket.bucket_type.value), + eviction_policy=EvictionPolicyType(bucket.eviction_policy.value), + max_ttl=bucket.max_ttl, + compression_mode=CompressionMode(bucket.compression_mode.value), + conflict_resolution_type=ConflictResolutionType(bucket.conflict_resolution_type.value) + ), CreateBucketOptions(timeout=timedelta(seconds=25))) except BucketAlreadyExistsException: pass diff --git a/cbcmgr/cb_operation_a.py b/cbcmgr/cb_operation_a.py index eadfc60..0129e1e 100644 --- a/cbcmgr/cb_operation_a.py +++ b/cbcmgr/cb_operation_a.py @@ -140,7 +140,7 @@ async def _bucket_(self, name: str): self._bucket = await self.get_bucket(self._cluster, name) except BucketNotFoundException: if self.create: - await self.create_bucket(self._cluster, name, self.quota, self.replicas, self.bucket_mode) + await self.create_bucket(self._cluster, name, self.quota, self.replicas, 0, False, self.bucket_mode) return await self._bucket_(name) else: raise diff --git a/cbcmgr/restmgr.py b/cbcmgr/restmgr.py index 214f659..fcefef1 100644 --- a/cbcmgr/restmgr.py +++ b/cbcmgr/restmgr.py @@ -241,10 +241,10 @@ def unique(self): return self.default() def page_url(self, endpoint: str, page: int, per_page: int) -> str: - return f"{self.url_prefix}/{endpoint}?page={page}&perPage={per_page}" + return f"{self.url_prefix}{endpoint}?page={page}&perPage={per_page}" def build_url(self, endpoint: str) -> str: - return f"{self.url_prefix}/{endpoint}" + return f"{self.url_prefix}{endpoint}" async def get_async(self, url: str): conn = TCPConnector(ssl_context=self.ssl_context) @@ -263,6 +263,7 @@ async def get_kv_async(self, url: str, key: str, value: str): async def get_capella_a(self, endpoint: str): data = [] url = self.page_url(endpoint, 1, 1) + logger.debug(f"Capella get {url}") cursor = self.get(url).validate().json() total_items = cursor.get('cursor', {}).get('pages', {}).get('totalItems', 1) diff --git a/tests/test_6.py b/tests/test_6.py index 2a61842..e58b908 100755 --- a/tests/test_6.py +++ b/tests/test_6.py @@ -3,15 +3,22 @@ import warnings import time import pytest +import logging from cbcmgr.cb_capella import Capella, CapellaCluster, AllowedCIDR, Credentials from cbcmgr.cb_bucket import Bucket warnings.filterwarnings("ignore") +logger = logging.getLogger() @pytest.mark.serial class TestCapella(object): + @classmethod + def setup_class(cls): + logging.basicConfig() + logger.setLevel(logging.DEBUG) + def test_1(self): project = Capella().get_project('pytest-project') project_id = project.get('id')