From e2c12e30222cd2e323cc21a9be34c22fcb236fca Mon Sep 17 00:00:00 2001 From: lky0312 <523175094@qq.com> Date: Thu, 28 Dec 2023 14:33:10 +0800 Subject: [PATCH 01/11] dew-01 --- prefect_huaweicloud/dew_block.py | 1093 +++++++++++++++++++++++++++++ prefect_huaweicloud/dew_client.py | 32 + prefect_huaweicloud/test_dew.py | 110 +++ 3 files changed, 1235 insertions(+) create mode 100644 prefect_huaweicloud/dew_block.py create mode 100644 prefect_huaweicloud/dew_client.py create mode 100644 prefect_huaweicloud/test_dew.py diff --git a/prefect_huaweicloud/dew_block.py b/prefect_huaweicloud/dew_block.py new file mode 100644 index 0000000..5f657d5 --- /dev/null +++ b/prefect_huaweicloud/dew_block.py @@ -0,0 +1,1093 @@ + +from typing import Any, Dict, List, Optional, Union +from logging import Logger +from pydantic import Field, SecretStr +# from prefect import get_run_logger, task +from prefect.blocks.abstract import SecretBlock +from prefect.utilities.asyncutils import run_sync_in_worker_thread, sync_compatible +from prefect.logging.loggers import get_logger, get_run_logger +from prefect.exceptions import MissingContextError +from prefect import task +from pydantic import VERSION as PYDANTIC_VERSION +import json +if PYDANTIC_VERSION.startswith("2."): + from pydantic.v1 import Field +else: + from pydantic import Field +from dew_client import DewClient +# from obs import DewClient +from huaweicloudsdkkms.v2.model import * +from huaweicloudsdkcore.exceptions import exceptions + +from huaweicloudsdkkms.v2.region.kms_region import KmsRegion +from huaweicloudsdkkps.v3.region.kps_region import KpsRegion +from huaweicloudsdkcsms.v1.region.csms_region import CsmsRegion +from huaweicloudsdkcsms.v1 import * +from huaweicloudsdkkms.v2 import * +from huaweicloudsdkkps.v3 import * +class DewBlock(SecretBlock): + + _logo_url = "https://res-static.hc-cdn.cn/cloudbu-site/public/header-icon/Storage/OBS.png" # noqa + _block_type_name = "HuaweiCloud DEW" + _documentation_url = ("https://support.huaweicloud.com/intl/zh-cn/sdk-python-devg-obs/obs_22_0100.html") # noqa + + huawei_cloud_access_key_id: Optional[SecretStr] = Field( + default=None, + description="A specific Huawei Cloud access key ID.", + title="Huawei Cloud Access Key ID:", + ) + huawei_cloud_secret_access_key: Optional[SecretStr] = Field( + default=None, + description="A specific Huawei Cloud secret access key.", + title="Huawei Cloud Access Key Secret:", + + ) + huawei_cloud_security_token: Optional[SecretStr] = Field( + default=None, + description="SecurityToken in the temporary access key, " + "You can select a temporary token or AK/SK for authentication", + title="Huawei Cloud Security Token", + ) + region_id:Optional[str] = Field( + default=None, + title="region id", + ) + def _get_dew_client(self) -> DewClient: + if not self.huawei_cloud_access_key_id or not self.huawei_cloud_secret_access_key: + raise Exception("please input both huawei_cloud_access_key_id and huawei_cloud_secret_access_key") + + return DewClient( + ak=self.huawei_cloud_access_key_id.get_secret_value(), + sk=self.huawei_cloud_secret_access_key.get_secret_value(), + region_id=self.region_id, + ) + async def read_secret(self): + pass + async def write_secret(self): + pass + @property + def logger(self) -> Logger: + """ + Returns a logger based on whether the ObjectStorageBlock + is called from within a flow or task run context. + If a run context is present, the logger property returns a run logger. + Else, it returns a default logger labeled with the class's name. + + Returns: + The run logger or a default logger with the class's name. + """ + try: + return get_run_logger() + except MissingContextError: + return get_logger(self.__class__.__name__) + + def create_key(self,key_alias=None, key_spec=None, key_usage=None, key_description=None, origin=None, enterprise_project_id=None, sequence=None, keystore_id=None,**kwargs): + try: + request = CreateKeyRequest() + request.body = CreateKeyRequestBody( + key_alias=key_alias, + key_spec=key_spec, + key_usage=key_usage, + key_description=key_description, + origin=origin, + enterprise_project_id=enterprise_project_id, + sequence=sequence, + keystore_id=keystore_id + ) + response =self._get_dew_client().kms_client.create_key(request) + self.logger.debug("Created key") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + + def delete_key(self,key_id=None,pending_days=None, sequence=None,**kwargs): + try: + request = DeleteKeyRequest() + request.body = ScheduleKeyDeletionRequestBody( + key_id=key_id, + pending_days=pending_days, + sequence=sequence + ) + response = self._get_dew_client().kms_client.delete_key(request) + self.logger.debug("Successfully delete_key") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def disable_key(self,key_id=None,sequence=None,**kwargs): + try: + request = DisableKeyRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response =self._get_dew_client().kms_client.disable_key(request) + self.logger.info("Successfully disable_key👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def enable_key(self,key_id=None, sequence=None,**kwargs): + try: + request = EnableKeyRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response =self._get_dew_client().kms_client.enable_key(request) + self.logger.info("Successfully enable_key👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def update_key_Alias(self,key_id=None, key_alias=None, sequence=None,**kwargs): + try: + request = UpdateKeyAliasRequest() + request.body = UpdateKeyAliasRequestBody( + key_alias=key_alias, + key_id=key_id, + sequence=sequence + ) + response =self._get_dew_client().kms_client.update_key_alias(request) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def update_key_description(self,key_id=None, key_description=None, sequence=None,**kwargs): + try: + request = UpdateKeyDescriptionRequest() + request.body = UpdateKeyDescriptionRequestBody( + key_id=key_id, + key_description=key_description, + sequence=sequence + ) + response =self._get_dew_client().kms_client.update_key_description(request) + self.logger.info("Successfully update_key_description👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def cancel_key_deletion(self,key_id=None,sequence=None,**kwargs): + try: + request = CancelKeyDeletionRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response = self._get_dew_client().kms_client.cancel_key_deletion(request) + self.logger.info("Successfully canccel key daletion👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + + def create_data_key(self,key_id,key_spec=None, datakey_length=None, sequence=None,**kwargs): + try: + request = CreateDatakeyRequest() + request.body = CreateDatakeyRequestBody( + key_id=key_id, + key_spec=key_spec, + datakey_length=datakey_length, + sequence=sequence + ) + response = self._get_dew_client().kms_client.create_datakey(request) + self.logger.info("Successfully created datakey👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def create_data_key_without_plaintext(self,key_id,key_spec=None, datakey_length=None, sequence=None,**kwargs): + try: + request = CreateDatakeyWithoutPlaintextRequest() + request.body = CreateDatakeyRequestBody( + key_id=key_id, + key_spec=key_spec, + datakey_length=datakey_length, + sequence=sequence + ) + response = self._get_dew_client().kms_client.create_datakey_without_plaintext(request) + self.logger.info("Successfully created datakey without plaintext👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def create_random(self,random_data_length=None, sequence=None,**kwargs): + try: + request = CreateRandomRequest() + request.body = GenRandomRequestBody( + random_data_length=random_data_length, + sequence=sequence + ) + response = self._get_dew_client().kms_client.create_random(request) + self.logger.info("Successfully created random👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def decrypt_data_key(self,key_id=None, cipher_text=None, datakey_cipher_length=None, sequence=None,**kwargs): + try: + request = DecryptDatakeyRequest() + request.body = DecryptDatakeyRequestBody( + key_id=key_id, + cipher_text=cipher_text, + datakey_cipher_length=datakey_cipher_length, + sequence=sequence + ) + response = self._get_dew_client().kms_client.decrypt_datakey(request) + self.logger.info("Successfully decrypted datakey👇") + self.logger.info(response) + return response + + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def encrypt_data_key(self,key_id=None, plain_text=None, datakey_plain_length=None, sequence=None,**kwargs): + try: + request = EncryptDatakeyRequest() + request.body = EncryptDatakeyRequestBody( + key_id=key_id, + plain_text=plain_text, + datakey_plain_length=datakey_plain_length, + sequence=sequence + + ) + response = self._get_dew_client().kms_client.encrypt_datakey(request) + self.logger.info("Successfully encrypted datakey👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + + def create_parameters_for_import(self,key_id,wrapping_algorithm=None, sequence=None,**kwargs): + try: + request = CreateParametersForImportRequest() + request.body = GetParametersForImportRequestBody( + key_id=key_id, + wrapping_algorithm=wrapping_algorithm, + sequence=sequence + ) + response = self._get_dew_client().kms_client.create_parameters_for_import(request) + self.logger.info("Successfully created parameters for import👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def delete_imported_key_material(self,key_id,sequence=None,**kwargs): + try: + request = DeleteImportedKeyMaterialRequest() + request.body = OperateKeyRequestBody( + key_id = key_id, + sequence=sequence + ) + response = self._get_dew_client().kms_client.delete_imported_key_material(request) + self.logger.info("Successfully deleted imported key material👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def import_key_material(self,key_id=None, import_token=None, encrypted_key_material=None, encrypted_privatekey=None, expiration_time=None, sequence=None,**kwargs): + try: + request = ImportKeyMaterialRequest() + request.body = ImportKeyMaterialRequestBody( + key_id=key_id, + import_token=import_token, + encrypted_key_material=encrypted_key_material, + encrypted_privatekey=encrypted_privatekey, + expiration_time=expiration_time, + sequence=sequence + ) + response = self._get_dew_client().kms_client.import_key_material(request) + self.logger.info("Successfully imported key material👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + + def create_grant(self,key_id=None, grantee_principal=None, listOperationsbody=[], name=None, retiring_principal=None, grantee_principal_type=None, sequence=None,**kwargs): + try: + request = CreateGrantRequest() + + request.body = CreateGrantRequestBody( + key_id=key_id, + grantee_principal=grantee_principal, + operations=listOperationsbody, + grantee_principal_type=grantee_principal_type, + retiring_principal=retiring_principal, + name=name, + sequence=sequence + ) + response = self._get_dew_client().kms_client.create_grant(request) + self.logger.info("Successfully create grant👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(e.status_code) + self.logger.error(e.request_id) + self.logger.error(e.error_code) + self.logger.error(e.error_msg) + def list_retirable_grants(self,limit=None, marker=None, sequence=None, **kwargs): + try: + request = ListRetirableGrantsRequest() + request.body = ListRetirableGrantsRequestBody( + limit=limit, + marker=marker, + sequence=sequence + ) + response = self._get_dew_client().kms_client.list_retirable_grants(request) + self.logger.info("Successfully list retirable grants👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(e.status_code) + self.logger.error(e.request_id) + self.logger.error(e.error_code) + self.logger.error(e.error_msg) + def list_grants(self,key_id=None, limit=None, marker=None, sequence=None,**kwargs): + try: + request = ListGrantsRequest() + request.body = ListGrantsRequestBody( + key_id=key_id, + limit=limit, + marker=marker, + sequence=sequence + ) + response = self._get_dew_client().kms_client.list_grants(request) + self.logger.info("Successfully list grants👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(e.status_code) + self.logger.error(e.request_id) + self.logger.error(e.error_code) + self.logger.error(e.error_msg) + def cancel_self_grant(self,key_id=None, grant_id=None, sequence=None,**kwargs): + try: + request = CancelSelfGrantRequest() + request.body = RevokeGrantRequestBody( + grant_id=grant_id, + key_id=key_id, + sequence=sequence + ) + response = self._get_dew_client().kms_client.cancel_self_grant(request) + self.logger.info("Successfully cancel self grant👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(e.status_code) + self.logger.error(e.request_id) + self.logger.error(e.error_code) + self.logger.error(e.error_msg) + def cancel_grant(self,key_id=None, grant_id=None, sequence=None,**kwargs): + try: + request = CancelGrantRequest() + request.body = RevokeGrantRequestBody( + grant_id=grant_id, + key_id=key_id, + sequence=sequence + ) + response = self._get_dew_client().kms_client.cancel_grant(request) + self.logger.info("Successfully cancel grant👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(e.status_code) + self.logger.error(e.request_id) + self.logger.error(e.error_code) + self.logger.error(e.error_msg) + + + def decrypt_data(self,cipher_text=None, encryption_algorithm=None, key_id=None, sequence=None,**kwargs): + try: + request = DecryptDataRequest() + request.body = DecryptDataRequestBody( + cipher_text=cipher_text, + encryption_algorithm=encryption_algorithm, + key_id=key_id, + sequence=sequence + ) + response = self._get_dew_client().kms_client.decrypt_data(request) + self.logger.info("Successfully decrypted data👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def encrypt_data(self,key_id=None,plain_text=None, encryption_algorithm=None, sequence=None,**kwargs): + try: + request = EncryptDataRequest() + request.body = EncryptDataRequestBody( + plain_text=plain_text, + key_id=key_id, + encryption_algorithm=encryption_algorithm, + sequence=sequence + ) + response = self._get_dew_client().kms_client.encrypt_data(request) + self.logger.info("Successfully encrypted data👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + + def list_key_detail(self,key_id=None,sequence=None,**kwargs): + try: + request = ListKeyDetailRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response = self._get_dew_client().kms_client.list_key_detail(request) + self.logger.info("Successfully list key detail👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def list_keys(self,limit=None, marker=None, key_state=None, key_spec=None, enterprise_project_id=None, sequence=None,**kwargs): + try: + request = ListKeysRequest() + request.body = ListKeysRequestBody( + limit=limit, + marker=marker, + key_state=key_state, + key_spec=key_spec, + enterprise_project_id=enterprise_project_id, + sequence=sequence + ) + response = self._get_dew_client().kms_client.list_keys(request) + # self.logger.error(response.to_dict()) + self.logger.error(json.dumps(response.to_dict()).replace('}','}\n')) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def show_public_key(self,key_id=None, sequence=None,**kwargs): + try: + request = ShowPublicKeyRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, sequence=sequence + ) + response = self._get_dew_client().kms_client.show_public_key(request) + self.logger.info("Successfully show public key👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def show_user_instances(self,**kwargs): + try: + request = ShowUserInstancesRequest() + response = self._get_dew_client().kms_client.show_user_instances(request) + self.logger.info("Successfully show user instances👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def show_user_quotas(self,**kwargs): + try: + request = ShowUserQuotasRequest() + response = self._get_dew_client().kms_client.show_user_quotas(request) + self.logger.info("Successfully show user quotas👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + + def show_version(self,**kwargs): + try: + request = ShowVersionRequest(kwargs) + response = self._get_dew_client().kms_client.show_version(request) + self.logger.info("Successfully show_version👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def show_versions(self,**kwargs): + try: + request = ShowVersionsRequest() + response = self._get_dew_client().kms_client.show_versions(request) + self.logger.info("Successfully show versions👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def create_keypair(self,name=None, type=None, public_key=None, scope=None, user_id=None, key_protection=None,**kwargs): + try: + request = CreateKeypairRequest() + keypairbody = CreateKeypairAction( + name=name, + type=type, + public_key=public_key, + scope=scope, + user_id=user_id, + key_protection=key_protection + ) + request.body = CreateKeypairRequestBody( + keypair=keypairbody + ) + response = self._get_dew_client().kps_client.create_keypair(request) + self.logger.info("Successfully created keypair👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def list_keypairs(self,limit=None, marker=None,**kwargs): + try: + request = ListKeypairsRequest( + limit=limit, + marker=marker + ) + response = self._get_dew_client().kps_client.list_keypairs(request) + self.logger.info("Successfully list keypairs👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def clear_private_key(self,keypair_name=None,**kwargs): + try: + request = ClearPrivateKeyRequest(keypair_name=keypair_name) + response = self._get_dew_client().kps_client.clear_private_key(request) + self.logger.info("Successfully cleared private key👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def import_private_key(self,user_id=None, name=None,type="default",kms_key_name="kps/default",private_key=None,**kwargs): + try: + request = ImportPrivateKeyRequest() + encryptionKeyProtection = Encryption( + type=type, + kms_key_name=kms_key_name + ) + keyProtectionKeypair = ImportPrivateKeyProtection( + private_key=private_key, + encryption=encryptionKeyProtection + ) + keypairbody = ImportPrivateKeyKeypairBean( + name=name, + key_protection=keyProtectionKeypair, + user_id=user_id + ) + request.body = ImportPrivateKeyRequestBody( + keypair=keypairbody + ) + response = self._get_dew_client().kps_client.import_private_key(request) + self.logger.info("Successfully import_private_key👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def list_keypair_detail(self,keypair_name=None,**kwargs): + try: + request = ListKeypairDetailRequest(keypair_name=keypair_name) + response = self._get_dew_client().kps_client.list_keypair_detail(request) + self.logger.info("Successfully exported private key👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def update_keypair_description(self,keypair_name=None,description=None,**kwargs): + try: + request = UpdateKeypairDescriptionRequest( + keypair_name=keypair_name + ) + keypairbody = UpdateKeypairDescriptionReq( + description=description + ) + request.body = UpdateKeypairDescriptionRequestBody( + keypair=keypairbody + ) + response = self._get_dew_client().kps_client.update_keypair_description(request) + self.logger.info("Successfully updated👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def export_private_key(self,name=None,**kwargs): + try: + request = ExportPrivateKeyRequest() + keypairbody = KeypairBean( + name=name + ) + request.body = ExportPrivateKeyRequestBody( + keypair=keypairbody + ) + response = self._get_dew_client().kps_client.export_private_key(request) + self.logger.info("Successfully exported private key👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def delete_keypair(self,keypair_name=None,**kwargs): + try: + request = DeleteKeypairRequest(keypair_name=keypair_name) + response = self._get_dew_client().kps_client.delete_keypair(request) + self.logger.info("Successfully deleted keypair") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def associate_keypair(self,keypair_name=None,type=None,key=None,id=None, disable_password=False, port=None,**kwargs): + try: + request = AssociateKeypairRequest() + authServer = Auth( + type=type, + key=key + ) + serverbody = EcsServerInfo( + id=id, + auth=authServer, + disable_password=disable_password, + port=port + ) + request.body = AssociateKeypairRequestBody( + server=serverbody, + keypair_name=keypair_name + ) + response = self._get_dew_client().kps_client.associate_keypair(request) + self.logger.info("Successfully associate_keypair👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def batch_associate_keypair(self,keypair_name=[],type=[],key=[],id=[],disable_password=[],port=[],**kwargs): + try: + request = BatchAssociateKeypairRequest() + listBatchKeypairsbody = [] + for s in range(len(keypair_name),**kwargs): + authServer = Auth( + type=type[s], + key=key[s] + ) + serverBatchKeypairs = EcsServerInfo( + id=id[s], + auth=authServer, + disable_password=disable_password[s], + port=port[s] + ) + listBatchKeypairsbody.append(AssociateKeypairRequestBody( + keypair_name=keypair_name[s], + server=serverBatchKeypairs + )) + + request.body = BatchAssociateKeypairRequestBody( + batch_keypairs=listBatchKeypairsbody + ) + response = self._get_dew_client().kps_client.batch_associate_keypair(request) + self.logger.info("Successfully batch_associate_keypair👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def delete_all_failed_task(self,**kwargs): + try: + request = DeleteAllFailedTaskRequest() + response = self._get_dew_client().kps_client.delete_all_failed_task(request) + self.logger.info("Successfully delete_all_failed_task👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def delete_failed_task(self,task_id,**kwargs): + try: + request = DeleteFailedTaskRequest( + task_id=task_id, + ) + response = self._get_dew_client().kps_client.delete_failed_task(request) + self.logger.info("Successfully delete_failed_task👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def disassociate_keypair(self,id=None,type=None,key=None,**kwargs): + try: + request = DisassociateKeypairRequest() + authServer = Auth( + type=type, + key=key + ) + serverbody = DisassociateEcsServerInfo( + id=id, + auth=authServer + ) + request.body = DisassociateKeypairRequestBody( + server=serverbody + ) + response = self._get_dew_client().kps_client.disassociate_keypair(request) + self.logger.info("Successfully disassociate_keypair👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def list_failed_task(self,limit=None, offset=None,**kwargs): + try: + request = ListFailedTaskRequest() + request.limit = limit + request.offset = offset + response = self._get_dew_client().kps_client.list_failed_task(request) + self.logger.info("Successfully list_failed_task👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def list_keypair_task(self,task_id=None,**kwargs): + try: + request = ListKeypairTaskRequest( + task_id=task_id + ) + response = self._get_dew_client().kps_client.list_keypair_task(request) + self.logger.info("Successfully list_keypair_task👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def list_running_task(self,limit=None,offset=None,**kwargs): + try: + request = ListRunningTaskRequest() + request.limit = limit + request.offset = offset + response = self._get_dew_client().kps_client.list_running_task(request) + self.logger.info("Successfully list_running_task👇") + + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def create_secret(self,name=None, kms_key_id=None, description=None, secret_binary=None, secret_string=None, secret_type=None, auto_rotation=None, rotation_period=None, rotation_config=None, event_subscriptions=None, enterprise_project_id=None,**kwargs): + try: + request = CreateSecretRequest() + request.body = CreateSecretRequestBody( + secret_string=secret_string, + kms_key_id=kms_key_id, + name=name, + description=description, + secret_binary=secret_binary, + secret_type=secret_type, + auto_rotation=auto_rotation, + rotation_period=rotation_period, + rotation_config=rotation_config, + event_subscriptions=event_subscriptions, + enterprise_project_id=enterprise_project_id + ) + response = self._get_dew_client().cms_client.create_secret(request) + self.logger.info("Successfully create_secret👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def download_secret_blob(self,secret_name:None,**kwargs): + try: + request = DownloadSecretBlobRequest( + secret_name=secret_name + ) + response = self._get_dew_client().cms_client.download_secret_blob(request) + self.logger.info("Successfully download_secret_blob👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def list_secrets(self,limit=None,marker=None,event_name=None,**kwargs): + try: + request = ListSecretsRequest() + request.limit = limit + request.marker = marker + request.event_name = event_name + response = self._get_dew_client().cms_client.list_secrets(request) + self.logger.info("Successfully list_secrets👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def show_secret(self,secret_name,**kwargs): + try: + request = ShowSecretRequest( + secret_name=secret_name + ) + response = self._get_dew_client().cms_client.show_secret(request) + self.logger.info("Successfully show_secret👇") + + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def update_secret(self,kms_key_id=None,secret_name=None, description=None, auto_rotation=None, rotation_period=None, listEventSubscriptionsbody=None,**kwargs): + try: + request = UpdateSecretRequest() + request.body = UpdateSecretRequestBody( + event_subscriptions=listEventSubscriptionsbody, + description=description, + kms_key_id=kms_key_id, + auto_rotation=auto_rotation, + rotation_period=rotation_period, + ) + request.secret_name=secret_name + response = self._get_dew_client().cms_client.update_secret(request) + self.logger.info("Successfully update_secret👇") + + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def create_secret_event(self,target_type=None, target_id=None, target_name=None,name=None, state=None, listEventTypesbody=[],**kwargs): + try: + request = CreateSecretEventRequest() + notificationbody = Notification( + target_type=target_type, + target_id=target_id, + target_name=target_name + ) + request.body = CreateSecretEventRequestBody( + notification=notificationbody, + state=state, + event_types=listEventTypesbody, + name=name, + ) + response = self._get_dew_client().cms_client.create_secret_event(request) + self.logger.info("Successfully create_secret_event👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def upload_secret_blob(self,secret_blob,**kwargs): + try: + request = UploadSecretBlobRequest() + request.body = UploadSecretBlobRequestBody( + secret_blob=secret_blob + ) + response = self._get_dew_client().cms_client.upload_secret_blob(request) + self.logger.info("Successfully upload_secret_blob👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(e.status_code) + self.logger.error(e.request_id) + self.logger.error(e.error_code) + def rotate_secret(self,secret_name=None,**kwargs): + try: + request = RotateSecretRequest( + secret_name=secret_name + ) + response = self._get_dew_client().cms_client.rotate_secret(request) + self.logger.info("Successfully rotate_secret👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def restore_secret(self,secret_name,**kwargs): + try: + request = RestoreSecretRequest(secret_name=secret_name) + response = self._get_dew_client().cms_client.restore_secret(request) + self.logger.info("Successfully restore_secret👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def delete_secret_for_schedule(self,recovery_window_in_days=None,secret_name=None,**kwargs): + try: + request = DeleteSecretForScheduleRequest(secret_name=secret_name) + request.body = DeleteSecretForScheduleRequestBody( + recovery_window_in_days=recovery_window_in_days + ) + response = self._get_dew_client().cms_client.delete_secret_for_schedule(request) + self.logger.info("Successfully delete_secret_for_schedule👇") + + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def delete_secret(self,secret_name,**kwargs): + try: + request = DeleteSecretRequest(secret_name=secret_name) + response = self._get_dew_client().cms_client.delete_secret(request) + self.logger.info("Successfully delete_secret👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + + def create_secret_version(self,secret_name=None,secret_binary=None, secret_string=None, version_stages=None, expire_time=None,**kwargs): + try: + request = CreateSecretVersionRequest(secret_name=secret_name) + request.body = CreateSecretVersionRequestBody( + secret_string=secret_string, + secret_binary=secret_binary, + version_stages=version_stages, + expire_time=expire_time + ) + response = self._get_dew_client().cms_client.create_secret_version(request) + self.logger.info("Successfully create_secret_version👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def list_secret_versions(self,secret_name=None, marker=None, limit=None,**kwargs): + try: + request = ListSecretVersionsRequest() + request.secret_name = secret_name + request.marker = marker + request.limit = limit + response = self._get_dew_client().cms_client.list_secret_versions(request) + self.logger.info("Successfully list_secret_versions👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + + def show_secret_version(self,secret_name=None,version_id=None,**kwargs): + try: + request = ShowSecretVersionRequest() + request.secret_name=secret_name + request.version_id = version_id + response = self._get_dew_client().cms_client.show_secret_version(request) + self.logger.info("Successfully show_secret_version👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + def update_version(self,secret_name=None, version_id=None, expire_time=None,**kwargs): + try: + request = UpdateVersionRequest() + request.version_id=version_id + request.secret_name=secret_name + request.body = UpdateVersionRequestBody( + expire_time=expire_time + ) + response = self._get_dew_client().cms_client.update_version(request) + self.logger.info("Successfully update_version👇") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + + diff --git a/prefect_huaweicloud/dew_client.py b/prefect_huaweicloud/dew_client.py new file mode 100644 index 0000000..b5e06f2 --- /dev/null +++ b/prefect_huaweicloud/dew_client.py @@ -0,0 +1,32 @@ +from huaweicloudsdkcore.auth.credentials import BasicCredentials +from huaweicloudsdkkms.v2.region.kms_region import KmsRegion +from huaweicloudsdkkms.v2 import * +from huaweicloudsdkkps.v3.region.kps_region import KpsRegion +from huaweicloudsdkkps.v3 import * +from huaweicloudsdkcsms.v1.region.csms_region import CsmsRegion +from huaweicloudsdkcsms.v1 import * +class DewClient(): + def __init__(self,region_id:str,ak:str,sk:str): + self.region_id=region_id + self.__ak=ak + self.__sk=sk + @property + def kms_client(self)->KmsClient: + return KmsClient.new_builder() \ + .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ + .with_region(KmsRegion.value_of(self.region_id)) \ + .build() + @property + def kps_client(self)->KpsClient: + return KpsClient.new_builder() \ + .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ + .with_region(KpsRegion.value_of(self.region_id)) \ + .build() + @property + def cms_client(self)->CsmsClient: + return CsmsClient.new_builder() \ + .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ + .with_region(CsmsRegion.value_of(self.region_id)) \ + .build() + + \ No newline at end of file diff --git a/prefect_huaweicloud/test_dew.py b/prefect_huaweicloud/test_dew.py new file mode 100644 index 0000000..6c77464 --- /dev/null +++ b/prefect_huaweicloud/test_dew.py @@ -0,0 +1,110 @@ +from dew_block import DewBlock +from prefect import flow,task + +def kms_params(huaweicloud_dew_block,key_alias=None): + test_key=huaweicloud_dew_block.create_key(key_alias=key_alias) + return dict( + key_alias=key_alias, + key_id=test_key.key_info.key_id, + key_description=None, + pending_days=7, + random_data_length=512, + datakey_length=512, + datakey_plain_length=64, + datakey_cipher_length=64, + cipher_text=None, + plain_text=None, + datakey_dgst=None, + + grantee_principal="0f9eaeef3b7347f3804c2b27d126273e", + listOperationsbody = [ + "describe-key", + "create-datakey", + "encrypt-datakey"], + grant_id=None, + encryption_algorithm="SYMMETRIC_DEFAULT" + ) + + +def kps_params(huaweicloud_dew_block,name): + key_pair_list=huaweicloud_dew_block.list_keypairs() + if name in list(x.keypair.name for x in key_pair_list.keypairs[:]): + huaweicloud_dew_block.delete_keypair(keypair_name=name) + test_key=huaweicloud_dew_block.create_keypair(name=name) + return dict( + name=name, + keypair_name=name, + private_key=test_key.keypair.private_key, + # key_id=test_key.keypair.user_id, + description=None + ) + +@flow +def test_key_lifecycle_management(kms_params,huaweicloud_dew_block): + row_key_alias=kms_params['key_alias'] + huaweicloud_dew_block.create_key(**kms_params) + huaweicloud_dew_block.disable_key(**kms_params) + huaweicloud_dew_block.enable_key(**kms_params) + kms_params['key_alias']="test_alias" + huaweicloud_dew_block.update_key_Alias(**kms_params) + kms_params['key_alias']=row_key_alias + huaweicloud_dew_block.update_key_Alias(**kms_params) + kms_params['key_description']="test_update_description" + huaweicloud_dew_block.update_key_description(**kms_params) + huaweicloud_dew_block.delete_key(**kms_params) + huaweicloud_dew_block.cancel_key_deletion(**kms_params) + huaweicloud_dew_block.enable_key(**kms_params) + +@flow +def test_data_key_management(kms_params,huaweicloud_dew_block): + huaweicloud_dew_block.create_data_key_without_plaintext(**kms_params) + create_data_key_response=huaweicloud_dew_block.create_data_key(**kms_params) + huaweicloud_dew_block.create_random(**kms_params) + kms_params["cipher_text"]=create_data_key_response.cipher_text + decrypt_data_key_response=huaweicloud_dew_block.decrypt_data_key(**kms_params) + kms_params["datakey_dgst"]=decrypt_data_key_response.datakey_dgst + kms_params["plain_text"]=decrypt_data_key_response.data_key+decrypt_data_key_response.datakey_dgst + huaweicloud_dew_block.encrypt_data_key(**kms_params) + + +@flow +def test_key_grant_management(kms_params,huaweicloud_dew_block): + create_grant_response=huaweicloud_dew_block.create_grant(**kms_params) + kms_params["grant_id"]=create_grant_response.grant_id + huaweicloud_dew_block.list_retirable_grants(**kms_params) + # huaweicloud_dew_block.cancel_self_grant(**kms_params) + huaweicloud_dew_block.cancel_grant(**kms_params) + huaweicloud_dew_block.list_grants(**kms_params) + + + + + +@flow +def test_key_pair_management(kps_params,huaweicloud_dew_block): + row_keypair_name=kps_params['name'] + huaweicloud_dew_block.import_private_key(**kps_params) + huaweicloud_dew_block.export_private_key(**kps_params) + huaweicloud_dew_block.list_keypair_detail(**kps_params) + huaweicloud_dew_block.clear_private_key(**kps_params) + + kps_params['description']="test_update_description" + huaweicloud_dew_block.update_keypair_description(**kps_params) + + huaweicloud_dew_block.delete_keypair(**kps_params) + +def test_small_data_encryption(kms_params,huaweicloud_dew_block): + encrypt_data_response=huaweicloud_dew_block.encrypt_data(**kms_params) + kms_params["cipher_text"]=encrypt_data_response.cipher_text + huaweicloud_dew_block.decrypt_data(**kms_params) + + +if __name__=="__main__": + huaweicloud_dew_block = DewBlock.load("test-dew-block") + kms_params=kms_params(huaweicloud_dew_block,key_alias="12-26") +# test_key_lifecycle_management(kms_params,huaweicloud_dew_block) +# test_key_pair_management(kps_params(huaweicloud_dew_block,name="22-22"),huaweicloud_dew_block) + test_data_key_management(kms_params,huaweicloud_dew_block) +# test_key_grant_management(kms_params,huaweicloud_dew_block) + test_small_data_encryption(kms_params,huaweicloud_dew_block) + \ No newline at end of file -- Gitee From 8603405a137269060ca186dda3f70f9eb2301b43 Mon Sep 17 00:00:00 2001 From: lky0312 <523175094@qq.com> Date: Thu, 28 Dec 2023 18:54:51 +0800 Subject: [PATCH 02/11] Modify some code specifications --- prefect_huaweicloud/dew_block.py | 310 ++++++++++++------ prefect_huaweicloud/dew_client.py | 24 +- prefect_huaweicloud/test/__init__.py | 3 + .../{test_dew.py => test/test_dew_block.py} | 57 +++- 4 files changed, 269 insertions(+), 125 deletions(-) create mode 100644 prefect_huaweicloud/test/__init__.py rename prefect_huaweicloud/{test_dew.py => test/test_dew_block.py} (68%) diff --git a/prefect_huaweicloud/dew_block.py b/prefect_huaweicloud/dew_block.py index 5f657d5..83feb0f 100644 --- a/prefect_huaweicloud/dew_block.py +++ b/prefect_huaweicloud/dew_block.py @@ -2,8 +2,7 @@ from typing import Any, Dict, List, Optional, Union from logging import Logger from pydantic import Field, SecretStr -# from prefect import get_run_logger, task -from prefect.blocks.abstract import SecretBlock +from prefect.blocks.abstract import Block from prefect.utilities.asyncutils import run_sync_in_worker_thread, sync_compatible from prefect.logging.loggers import get_logger, get_run_logger from prefect.exceptions import MissingContextError @@ -15,17 +14,13 @@ if PYDANTIC_VERSION.startswith("2."): else: from pydantic import Field from dew_client import DewClient -# from obs import DewClient from huaweicloudsdkkms.v2.model import * from huaweicloudsdkcore.exceptions import exceptions +from huaweicloudsdkcsms.v1.model import * +from huaweicloudsdkkps.v3.model import * -from huaweicloudsdkkms.v2.region.kms_region import KmsRegion -from huaweicloudsdkkps.v3.region.kps_region import KpsRegion -from huaweicloudsdkcsms.v1.region.csms_region import CsmsRegion -from huaweicloudsdkcsms.v1 import * -from huaweicloudsdkkms.v2 import * -from huaweicloudsdkkps.v3 import * -class DewBlock(SecretBlock): + +class DewBlock(Block): _logo_url = "https://res-static.hc-cdn.cn/cloudbu-site/public/header-icon/Storage/OBS.png" # noqa _block_type_name = "HuaweiCloud DEW" @@ -39,8 +34,7 @@ class DewBlock(SecretBlock): huawei_cloud_secret_access_key: Optional[SecretStr] = Field( default=None, description="A specific Huawei Cloud secret access key.", - title="Huawei Cloud Access Key Secret:", - + title="Huawei Cloud Access Key Secret:", ) huawei_cloud_security_token: Optional[SecretStr] = Field( default=None, @@ -52,19 +46,12 @@ class DewBlock(SecretBlock): default=None, title="region id", ) - def _get_dew_client(self) -> DewClient: - if not self.huawei_cloud_access_key_id or not self.huawei_cloud_secret_access_key: - raise Exception("please input both huawei_cloud_access_key_id and huawei_cloud_secret_access_key") + + def __init__(self,*args,**kwargs): + self.dew_client=DewClient(region_id=kwargs['region_id'], + ak=kwargs['huawei_cloud_access_key_id'], + sk=kwargs['huawei_cloud_secret_access_key']) - return DewClient( - ak=self.huawei_cloud_access_key_id.get_secret_value(), - sk=self.huawei_cloud_secret_access_key.get_secret_value(), - region_id=self.region_id, - ) - async def read_secret(self): - pass - async def write_secret(self): - pass @property def logger(self) -> Logger: """ @@ -81,7 +68,8 @@ class DewBlock(SecretBlock): except MissingContextError: return get_logger(self.__class__.__name__) - def create_key(self,key_alias=None, key_spec=None, key_usage=None, key_description=None, origin=None, enterprise_project_id=None, sequence=None, keystore_id=None,**kwargs): + def create_key(self,key_alias=None, key_spec=None, key_usage=None, key_description=None, + origin=None, enterprise_project_id=None, sequence=None, keystore_id=None,**kwargs): try: request = CreateKeyRequest() request.body = CreateKeyRequestBody( @@ -94,7 +82,7 @@ class DewBlock(SecretBlock): sequence=sequence, keystore_id=keystore_id ) - response =self._get_dew_client().kms_client.create_key(request) + response =self.dew_client.kms_client.create_key(request) self.logger.debug("Created key") self.logger.info(response) return response @@ -112,7 +100,7 @@ class DewBlock(SecretBlock): pending_days=pending_days, sequence=sequence ) - response = self._get_dew_client().kms_client.delete_key(request) + response = self.dew_client.kms_client.delete_key(request) self.logger.debug("Successfully delete_key") self.logger.info(response) return response @@ -121,6 +109,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def disable_key(self,key_id=None,sequence=None,**kwargs): try: request = DisableKeyRequest() @@ -128,7 +117,7 @@ class DewBlock(SecretBlock): key_id=key_id, sequence=sequence ) - response =self._get_dew_client().kms_client.disable_key(request) + response =self.dew_client.kms_client.disable_key(request) self.logger.info("Successfully disable_key👇") self.logger.info(response) return response @@ -137,6 +126,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def enable_key(self,key_id=None, sequence=None,**kwargs): try: request = EnableKeyRequest() @@ -144,7 +134,7 @@ class DewBlock(SecretBlock): key_id=key_id, sequence=sequence ) - response =self._get_dew_client().kms_client.enable_key(request) + response =self.dew_client.kms_client.enable_key(request) self.logger.info("Successfully enable_key👇") self.logger.info(response) return response @@ -153,6 +143,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def update_key_Alias(self,key_id=None, key_alias=None, sequence=None,**kwargs): try: request = UpdateKeyAliasRequest() @@ -161,13 +152,14 @@ class DewBlock(SecretBlock): key_id=key_id, sequence=sequence ) - response =self._get_dew_client().kms_client.update_key_alias(request) + response =self.dew_client.kms_client.update_key_alias(request) return response except exceptions.ClientRequestException as e: self.logger.error("status_code= %s",e.status_code) self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def update_key_description(self,key_id=None, key_description=None, sequence=None,**kwargs): try: request = UpdateKeyDescriptionRequest() @@ -176,7 +168,7 @@ class DewBlock(SecretBlock): key_description=key_description, sequence=sequence ) - response =self._get_dew_client().kms_client.update_key_description(request) + response =self.dew_client.kms_client.update_key_description(request) self.logger.info("Successfully update_key_description👇") self.logger.info(response) return response @@ -185,6 +177,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def cancel_key_deletion(self,key_id=None,sequence=None,**kwargs): try: request = CancelKeyDeletionRequest() @@ -192,7 +185,7 @@ class DewBlock(SecretBlock): key_id=key_id, sequence=sequence ) - response = self._get_dew_client().kms_client.cancel_key_deletion(request) + response = self.dew_client.kms_client.cancel_key_deletion(request) self.logger.info("Successfully canccel key daletion👇") self.logger.info(response) return response @@ -211,7 +204,7 @@ class DewBlock(SecretBlock): datakey_length=datakey_length, sequence=sequence ) - response = self._get_dew_client().kms_client.create_datakey(request) + response = self.dew_client.kms_client.create_datakey(request) self.logger.info("Successfully created datakey👇") self.logger.info(response) return response @@ -220,6 +213,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def create_data_key_without_plaintext(self,key_id,key_spec=None, datakey_length=None, sequence=None,**kwargs): try: request = CreateDatakeyWithoutPlaintextRequest() @@ -229,7 +223,7 @@ class DewBlock(SecretBlock): datakey_length=datakey_length, sequence=sequence ) - response = self._get_dew_client().kms_client.create_datakey_without_plaintext(request) + response = self.dew_client.kms_client.create_datakey_without_plaintext(request) self.logger.info("Successfully created datakey without plaintext👇") self.logger.info(response) return response @@ -238,6 +232,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def create_random(self,random_data_length=None, sequence=None,**kwargs): try: request = CreateRandomRequest() @@ -245,7 +240,7 @@ class DewBlock(SecretBlock): random_data_length=random_data_length, sequence=sequence ) - response = self._get_dew_client().kms_client.create_random(request) + response = self.dew_client.kms_client.create_random(request) self.logger.info("Successfully created random👇") self.logger.info(response) return response @@ -254,6 +249,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def decrypt_data_key(self,key_id=None, cipher_text=None, datakey_cipher_length=None, sequence=None,**kwargs): try: request = DecryptDatakeyRequest() @@ -263,7 +259,7 @@ class DewBlock(SecretBlock): datakey_cipher_length=datakey_cipher_length, sequence=sequence ) - response = self._get_dew_client().kms_client.decrypt_datakey(request) + response = self.dew_client.kms_client.decrypt_datakey(request) self.logger.info("Successfully decrypted datakey👇") self.logger.info(response) return response @@ -273,6 +269,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def encrypt_data_key(self,key_id=None, plain_text=None, datakey_plain_length=None, sequence=None,**kwargs): try: request = EncryptDatakeyRequest() @@ -281,9 +278,8 @@ class DewBlock(SecretBlock): plain_text=plain_text, datakey_plain_length=datakey_plain_length, sequence=sequence - ) - response = self._get_dew_client().kms_client.encrypt_datakey(request) + response = self.dew_client.kms_client.encrypt_datakey(request) self.logger.info("Successfully encrypted datakey👇") self.logger.info(response) return response @@ -301,7 +297,7 @@ class DewBlock(SecretBlock): wrapping_algorithm=wrapping_algorithm, sequence=sequence ) - response = self._get_dew_client().kms_client.create_parameters_for_import(request) + response = self.dew_client.kms_client.create_parameters_for_import(request) self.logger.info("Successfully created parameters for import👇") self.logger.info(response) return response @@ -310,6 +306,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def delete_imported_key_material(self,key_id,sequence=None,**kwargs): try: request = DeleteImportedKeyMaterialRequest() @@ -317,7 +314,7 @@ class DewBlock(SecretBlock): key_id = key_id, sequence=sequence ) - response = self._get_dew_client().kms_client.delete_imported_key_material(request) + response = self.dew_client.kms_client.delete_imported_key_material(request) self.logger.info("Successfully deleted imported key material👇") self.logger.info(response) return response @@ -326,7 +323,10 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) - def import_key_material(self,key_id=None, import_token=None, encrypted_key_material=None, encrypted_privatekey=None, expiration_time=None, sequence=None,**kwargs): + + def import_key_material(self,key_id=None, import_token=None, + encrypted_key_material=None, encrypted_privatekey=None, + expiration_time=None, sequence=None, **kwargs): try: request = ImportKeyMaterialRequest() request.body = ImportKeyMaterialRequestBody( @@ -337,7 +337,7 @@ class DewBlock(SecretBlock): expiration_time=expiration_time, sequence=sequence ) - response = self._get_dew_client().kms_client.import_key_material(request) + response = self.dew_client.kms_client.import_key_material(request) self.logger.info("Successfully imported key material👇") self.logger.info(response) return response @@ -347,7 +347,8 @@ class DewBlock(SecretBlock): self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) - def create_grant(self,key_id=None, grantee_principal=None, listOperationsbody=[], name=None, retiring_principal=None, grantee_principal_type=None, sequence=None,**kwargs): + def create_grant(self,key_id=None, grantee_principal=None, listOperationsbody=[], + name=None, retiring_principal=None, grantee_principal_type=None, sequence=None,**kwargs): try: request = CreateGrantRequest() @@ -360,7 +361,7 @@ class DewBlock(SecretBlock): name=name, sequence=sequence ) - response = self._get_dew_client().kms_client.create_grant(request) + response = self.dew_client.kms_client.create_grant(request) self.logger.info("Successfully create grant👇") self.logger.info(response) return response @@ -369,6 +370,7 @@ class DewBlock(SecretBlock): self.logger.error(e.request_id) self.logger.error(e.error_code) self.logger.error(e.error_msg) + def list_retirable_grants(self,limit=None, marker=None, sequence=None, **kwargs): try: request = ListRetirableGrantsRequest() @@ -377,7 +379,7 @@ class DewBlock(SecretBlock): marker=marker, sequence=sequence ) - response = self._get_dew_client().kms_client.list_retirable_grants(request) + response = self.dew_client.kms_client.list_retirable_grants(request) self.logger.info("Successfully list retirable grants👇") self.logger.info(response) return response @@ -386,6 +388,7 @@ class DewBlock(SecretBlock): self.logger.error(e.request_id) self.logger.error(e.error_code) self.logger.error(e.error_msg) + def list_grants(self,key_id=None, limit=None, marker=None, sequence=None,**kwargs): try: request = ListGrantsRequest() @@ -395,7 +398,7 @@ class DewBlock(SecretBlock): marker=marker, sequence=sequence ) - response = self._get_dew_client().kms_client.list_grants(request) + response = self.dew_client.kms_client.list_grants(request) self.logger.info("Successfully list grants👇") self.logger.info(response) return response @@ -404,6 +407,7 @@ class DewBlock(SecretBlock): self.logger.error(e.request_id) self.logger.error(e.error_code) self.logger.error(e.error_msg) + def cancel_self_grant(self,key_id=None, grant_id=None, sequence=None,**kwargs): try: request = CancelSelfGrantRequest() @@ -412,7 +416,7 @@ class DewBlock(SecretBlock): key_id=key_id, sequence=sequence ) - response = self._get_dew_client().kms_client.cancel_self_grant(request) + response = self.dew_client.kms_client.cancel_self_grant(request) self.logger.info("Successfully cancel self grant👇") self.logger.info(response) return response @@ -421,6 +425,7 @@ class DewBlock(SecretBlock): self.logger.error(e.request_id) self.logger.error(e.error_code) self.logger.error(e.error_msg) + def cancel_grant(self,key_id=None, grant_id=None, sequence=None,**kwargs): try: request = CancelGrantRequest() @@ -429,7 +434,7 @@ class DewBlock(SecretBlock): key_id=key_id, sequence=sequence ) - response = self._get_dew_client().kms_client.cancel_grant(request) + response = self.dew_client.kms_client.cancel_grant(request) self.logger.info("Successfully cancel grant👇") self.logger.info(response) return response @@ -449,7 +454,7 @@ class DewBlock(SecretBlock): key_id=key_id, sequence=sequence ) - response = self._get_dew_client().kms_client.decrypt_data(request) + response = self.dew_client.kms_client.decrypt_data(request) self.logger.info("Successfully decrypted data👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -457,6 +462,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def encrypt_data(self,key_id=None,plain_text=None, encryption_algorithm=None, sequence=None,**kwargs): try: request = EncryptDataRequest() @@ -466,7 +472,7 @@ class DewBlock(SecretBlock): encryption_algorithm=encryption_algorithm, sequence=sequence ) - response = self._get_dew_client().kms_client.encrypt_data(request) + response = self.dew_client.kms_client.encrypt_data(request) self.logger.info("Successfully encrypted data👇") self.logger.info(response) return response @@ -483,7 +489,7 @@ class DewBlock(SecretBlock): key_id=key_id, sequence=sequence ) - response = self._get_dew_client().kms_client.list_key_detail(request) + response = self.dew_client.kms_client.list_key_detail(request) self.logger.info("Successfully list key detail👇") self.logger.info(response) return response @@ -492,7 +498,9 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) - def list_keys(self,limit=None, marker=None, key_state=None, key_spec=None, enterprise_project_id=None, sequence=None,**kwargs): + + def list_keys(self,limit=None, marker=None, key_state=None, key_spec=None, + enterprise_project_id=None, sequence=None,**kwargs): try: request = ListKeysRequest() request.body = ListKeysRequestBody( @@ -503,7 +511,7 @@ class DewBlock(SecretBlock): enterprise_project_id=enterprise_project_id, sequence=sequence ) - response = self._get_dew_client().kms_client.list_keys(request) + response = self.dew_client.kms_client.list_keys(request) # self.logger.error(response.to_dict()) self.logger.error(json.dumps(response.to_dict()).replace('}','}\n')) return response @@ -512,13 +520,15 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def show_public_key(self,key_id=None, sequence=None,**kwargs): try: request = ShowPublicKeyRequest() request.body = OperateKeyRequestBody( - key_id=key_id, sequence=sequence + key_id=key_id, + sequence=sequence ) - response = self._get_dew_client().kms_client.show_public_key(request) + response = self.dew_client.kms_client.show_public_key(request) self.logger.info("Successfully show public key👇") self.logger.info(response) return response @@ -527,10 +537,11 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def show_user_instances(self,**kwargs): try: request = ShowUserInstancesRequest() - response = self._get_dew_client().kms_client.show_user_instances(request) + response = self.dew_client.kms_client.show_user_instances(request) self.logger.info("Successfully show user instances👇") self.logger.info(response) return response @@ -539,10 +550,11 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def show_user_quotas(self,**kwargs): try: request = ShowUserQuotasRequest() - response = self._get_dew_client().kms_client.show_user_quotas(request) + response = self.dew_client.kms_client.show_user_quotas(request) self.logger.info("Successfully show user quotas👇") self.logger.info(response) return response @@ -552,10 +564,10 @@ class DewBlock(SecretBlock): self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) - def show_version(self,**kwargs): + def show_version(self, **kwargs): try: request = ShowVersionRequest(kwargs) - response = self._get_dew_client().kms_client.show_version(request) + response = self.dew_client.kms_client.show_version(request) self.logger.info("Successfully show_version👇") self.logger.info(response) return response @@ -564,10 +576,11 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def show_versions(self,**kwargs): try: request = ShowVersionsRequest() - response = self._get_dew_client().kms_client.show_versions(request) + response = self.dew_client.kms_client.show_versions(request) self.logger.info("Successfully show versions👇") self.logger.info(response) return response @@ -576,7 +589,77 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) - def create_keypair(self,name=None, type=None, public_key=None, scope=None, user_id=None, key_protection=None,**kwargs): + + def disable_key_rotation(self, key_id=None, sequence=None, **kwargs): + try: + request = DisableKeyRotationRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.disable_key_rotation(request) + self.logger.info("Successfully disable key rotation👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + + def enable_key_rotation(self, key_id=None, sequence=None, **kwargs): + try: + request = EnableKeyRotationRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.enable_key_rotation(request) + self.logger.info("Successfully enable key rotation👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + + def show_key_rotation_status(self, key_id=None, sequence=None, **kwargs): + try: + request = ShowKeyRotationStatusRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.show_key_rotation_status(request) + self.logger.info("Successfully show key rotation status👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + + def update_key_rotation_interval(self, key_id=None, rotation_interval=None, sequence=None, **kwargs): + try: + request = UpdateKeyRotationIntervalRequest() + request.body = UpdateKeyRotationIntervalRequestBody( + rotation_interval=rotation_interval, + key_id=key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.update_key_rotation_interval(request) + self.logger.info("Successfully update key rotation interval👇") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error("status_code= %s",e.status_code) + self.logger.error("request_id= %s",e.request_id) + self.logger.error("error_code= %s",e.error_code) + self.logger.error("error_msg= %s",e.error_msg) + + def create_keypair(self,name=None, type=None, public_key=None, scope=None, user_id=None, key_protection=None, **kwargs): try: request = CreateKeypairRequest() keypairbody = CreateKeypairAction( @@ -590,7 +673,7 @@ class DewBlock(SecretBlock): request.body = CreateKeypairRequestBody( keypair=keypairbody ) - response = self._get_dew_client().kps_client.create_keypair(request) + response = self.dew_client.kps_client.create_keypair(request) self.logger.info("Successfully created keypair👇") self.logger.info(response) return response @@ -599,13 +682,14 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def list_keypairs(self,limit=None, marker=None,**kwargs): try: request = ListKeypairsRequest( limit=limit, marker=marker ) - response = self._get_dew_client().kps_client.list_keypairs(request) + response = self.dew_client.kps_client.list_keypairs(request) self.logger.info("Successfully list keypairs👇") self.logger.info(response) return response @@ -614,10 +698,11 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def clear_private_key(self,keypair_name=None,**kwargs): try: request = ClearPrivateKeyRequest(keypair_name=keypair_name) - response = self._get_dew_client().kps_client.clear_private_key(request) + response = self.dew_client.kps_client.clear_private_key(request) self.logger.info("Successfully cleared private key👇") self.logger.info(response) return response @@ -626,6 +711,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def import_private_key(self,user_id=None, name=None,type="default",kms_key_name="kps/default",private_key=None,**kwargs): try: request = ImportPrivateKeyRequest() @@ -645,7 +731,7 @@ class DewBlock(SecretBlock): request.body = ImportPrivateKeyRequestBody( keypair=keypairbody ) - response = self._get_dew_client().kps_client.import_private_key(request) + response = self.dew_client.kps_client.import_private_key(request) self.logger.info("Successfully import_private_key👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -653,10 +739,11 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def list_keypair_detail(self,keypair_name=None,**kwargs): try: request = ListKeypairDetailRequest(keypair_name=keypair_name) - response = self._get_dew_client().kps_client.list_keypair_detail(request) + response = self.dew_client.kps_client.list_keypair_detail(request) self.logger.info("Successfully exported private key👇") self.logger.info(response) return response @@ -665,6 +752,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def update_keypair_description(self,keypair_name=None,description=None,**kwargs): try: request = UpdateKeypairDescriptionRequest( @@ -676,7 +764,7 @@ class DewBlock(SecretBlock): request.body = UpdateKeypairDescriptionRequestBody( keypair=keypairbody ) - response = self._get_dew_client().kps_client.update_keypair_description(request) + response = self.dew_client.kps_client.update_keypair_description(request) self.logger.info("Successfully updated👇") self.logger.info(response) return response @@ -685,6 +773,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def export_private_key(self,name=None,**kwargs): try: request = ExportPrivateKeyRequest() @@ -694,7 +783,7 @@ class DewBlock(SecretBlock): request.body = ExportPrivateKeyRequestBody( keypair=keypairbody ) - response = self._get_dew_client().kps_client.export_private_key(request) + response = self.dew_client.kps_client.export_private_key(request) self.logger.info("Successfully exported private key👇") self.logger.info(response) return response @@ -703,10 +792,11 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def delete_keypair(self,keypair_name=None,**kwargs): try: request = DeleteKeypairRequest(keypair_name=keypair_name) - response = self._get_dew_client().kps_client.delete_keypair(request) + response = self.dew_client.kps_client.delete_keypair(request) self.logger.info("Successfully deleted keypair") self.logger.info(response) return response @@ -715,6 +805,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def associate_keypair(self,keypair_name=None,type=None,key=None,id=None, disable_password=False, port=None,**kwargs): try: request = AssociateKeypairRequest() @@ -732,7 +823,7 @@ class DewBlock(SecretBlock): server=serverbody, keypair_name=keypair_name ) - response = self._get_dew_client().kps_client.associate_keypair(request) + response = self.dew_client.kps_client.associate_keypair(request) self.logger.info("Successfully associate_keypair👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -740,6 +831,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def batch_associate_keypair(self,keypair_name=[],type=[],key=[],id=[],disable_password=[],port=[],**kwargs): try: request = BatchAssociateKeypairRequest() @@ -763,7 +855,7 @@ class DewBlock(SecretBlock): request.body = BatchAssociateKeypairRequestBody( batch_keypairs=listBatchKeypairsbody ) - response = self._get_dew_client().kps_client.batch_associate_keypair(request) + response = self.dew_client.kps_client.batch_associate_keypair(request) self.logger.info("Successfully batch_associate_keypair👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -771,10 +863,11 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def delete_all_failed_task(self,**kwargs): try: request = DeleteAllFailedTaskRequest() - response = self._get_dew_client().kps_client.delete_all_failed_task(request) + response = self.dew_client.kps_client.delete_all_failed_task(request) self.logger.info("Successfully delete_all_failed_task👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -782,12 +875,13 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def delete_failed_task(self,task_id,**kwargs): try: request = DeleteFailedTaskRequest( task_id=task_id, ) - response = self._get_dew_client().kps_client.delete_failed_task(request) + response = self.dew_client.kps_client.delete_failed_task(request) self.logger.info("Successfully delete_failed_task👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -795,6 +889,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def disassociate_keypair(self,id=None,type=None,key=None,**kwargs): try: request = DisassociateKeypairRequest() @@ -809,7 +904,7 @@ class DewBlock(SecretBlock): request.body = DisassociateKeypairRequestBody( server=serverbody ) - response = self._get_dew_client().kps_client.disassociate_keypair(request) + response = self.dew_client.kps_client.disassociate_keypair(request) self.logger.info("Successfully disassociate_keypair👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -817,12 +912,13 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def list_failed_task(self,limit=None, offset=None,**kwargs): try: request = ListFailedTaskRequest() request.limit = limit request.offset = offset - response = self._get_dew_client().kps_client.list_failed_task(request) + response = self.dew_client.kps_client.list_failed_task(request) self.logger.info("Successfully list_failed_task👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -830,12 +926,13 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def list_keypair_task(self,task_id=None,**kwargs): try: request = ListKeypairTaskRequest( task_id=task_id ) - response = self._get_dew_client().kps_client.list_keypair_task(request) + response = self.dew_client.kps_client.list_keypair_task(request) self.logger.info("Successfully list_keypair_task👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -843,12 +940,13 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def list_running_task(self,limit=None,offset=None,**kwargs): try: request = ListRunningTaskRequest() request.limit = limit request.offset = offset - response = self._get_dew_client().kps_client.list_running_task(request) + response = self.dew_client.kps_client.list_running_task(request) self.logger.info("Successfully list_running_task👇") self.logger.info(response) @@ -857,7 +955,11 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) - def create_secret(self,name=None, kms_key_id=None, description=None, secret_binary=None, secret_string=None, secret_type=None, auto_rotation=None, rotation_period=None, rotation_config=None, event_subscriptions=None, enterprise_project_id=None,**kwargs): + + def create_secret(self,name=None, kms_key_id=None, description=None, + secret_binary=None, secret_string=None, secret_type=None, + auto_rotation=None, rotation_period=None, rotation_config=None, + event_subscriptions=None, enterprise_project_id=None,**kwargs): try: request = CreateSecretRequest() request.body = CreateSecretRequestBody( @@ -873,7 +975,7 @@ class DewBlock(SecretBlock): event_subscriptions=event_subscriptions, enterprise_project_id=enterprise_project_id ) - response = self._get_dew_client().cms_client.create_secret(request) + response = self.dew_client.cms_client.create_secret(request) self.logger.info("Successfully create_secret👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -881,12 +983,13 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def download_secret_blob(self,secret_name:None,**kwargs): try: request = DownloadSecretBlobRequest( secret_name=secret_name ) - response = self._get_dew_client().cms_client.download_secret_blob(request) + response = self.dew_client.cms_client.download_secret_blob(request) self.logger.info("Successfully download_secret_blob👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -894,13 +997,14 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def list_secrets(self,limit=None,marker=None,event_name=None,**kwargs): try: request = ListSecretsRequest() request.limit = limit request.marker = marker request.event_name = event_name - response = self._get_dew_client().cms_client.list_secrets(request) + response = self.dew_client.cms_client.list_secrets(request) self.logger.info("Successfully list_secrets👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -908,12 +1012,13 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def show_secret(self,secret_name,**kwargs): try: request = ShowSecretRequest( secret_name=secret_name ) - response = self._get_dew_client().cms_client.show_secret(request) + response = self.dew_client.cms_client.show_secret(request) self.logger.info("Successfully show_secret👇") self.logger.info(response) @@ -922,7 +1027,9 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) - def update_secret(self,kms_key_id=None,secret_name=None, description=None, auto_rotation=None, rotation_period=None, listEventSubscriptionsbody=None,**kwargs): + + def update_secret(self,kms_key_id=None,secret_name=None, description=None, + auto_rotation=None, rotation_period=None, listEventSubscriptionsbody=None,**kwargs): try: request = UpdateSecretRequest() request.body = UpdateSecretRequestBody( @@ -933,7 +1040,7 @@ class DewBlock(SecretBlock): rotation_period=rotation_period, ) request.secret_name=secret_name - response = self._get_dew_client().cms_client.update_secret(request) + response = self.dew_client.cms_client.update_secret(request) self.logger.info("Successfully update_secret👇") self.logger.info(response) @@ -942,7 +1049,10 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) - def create_secret_event(self,target_type=None, target_id=None, target_name=None,name=None, state=None, listEventTypesbody=[],**kwargs): + + def create_secret_event(self,target_type=None, target_id=None, + target_name=None,name=None, state=None, + listEventTypesbody=[],**kwargs): try: request = CreateSecretEventRequest() notificationbody = Notification( @@ -956,7 +1066,7 @@ class DewBlock(SecretBlock): event_types=listEventTypesbody, name=name, ) - response = self._get_dew_client().cms_client.create_secret_event(request) + response = self.dew_client.cms_client.create_secret_event(request) self.logger.info("Successfully create_secret_event👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -964,25 +1074,27 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def upload_secret_blob(self,secret_blob,**kwargs): try: request = UploadSecretBlobRequest() request.body = UploadSecretBlobRequestBody( secret_blob=secret_blob ) - response = self._get_dew_client().cms_client.upload_secret_blob(request) + response = self.dew_client.cms_client.upload_secret_blob(request) self.logger.info("Successfully upload_secret_blob👇") self.logger.info(response) except exceptions.ClientRequestException as e: self.logger.error(e.status_code) self.logger.error(e.request_id) self.logger.error(e.error_code) + def rotate_secret(self,secret_name=None,**kwargs): try: request = RotateSecretRequest( secret_name=secret_name ) - response = self._get_dew_client().cms_client.rotate_secret(request) + response = self.dew_client.cms_client.rotate_secret(request) self.logger.info("Successfully rotate_secret👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -990,10 +1102,11 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def restore_secret(self,secret_name,**kwargs): try: request = RestoreSecretRequest(secret_name=secret_name) - response = self._get_dew_client().cms_client.restore_secret(request) + response = self.dew_client.cms_client.restore_secret(request) self.logger.info("Successfully restore_secret👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -1001,13 +1114,14 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def delete_secret_for_schedule(self,recovery_window_in_days=None,secret_name=None,**kwargs): try: request = DeleteSecretForScheduleRequest(secret_name=secret_name) request.body = DeleteSecretForScheduleRequestBody( recovery_window_in_days=recovery_window_in_days ) - response = self._get_dew_client().cms_client.delete_secret_for_schedule(request) + response = self.dew_client.cms_client.delete_secret_for_schedule(request) self.logger.info("Successfully delete_secret_for_schedule👇") self.logger.info(response) @@ -1016,10 +1130,11 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def delete_secret(self,secret_name,**kwargs): try: request = DeleteSecretRequest(secret_name=secret_name) - response = self._get_dew_client().cms_client.delete_secret(request) + response = self.dew_client.cms_client.delete_secret(request) self.logger.info("Successfully delete_secret👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -1028,7 +1143,8 @@ class DewBlock(SecretBlock): self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) - def create_secret_version(self,secret_name=None,secret_binary=None, secret_string=None, version_stages=None, expire_time=None,**kwargs): + def create_secret_version(self,secret_name=None,secret_binary=None, + secret_string=None, version_stages=None, expire_time=None,**kwargs): try: request = CreateSecretVersionRequest(secret_name=secret_name) request.body = CreateSecretVersionRequestBody( @@ -1037,7 +1153,7 @@ class DewBlock(SecretBlock): version_stages=version_stages, expire_time=expire_time ) - response = self._get_dew_client().cms_client.create_secret_version(request) + response = self.dew_client.cms_client.create_secret_version(request) self.logger.info("Successfully create_secret_version👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -1045,13 +1161,14 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def list_secret_versions(self,secret_name=None, marker=None, limit=None,**kwargs): try: request = ListSecretVersionsRequest() request.secret_name = secret_name request.marker = marker request.limit = limit - response = self._get_dew_client().cms_client.list_secret_versions(request) + response = self.dew_client.cms_client.list_secret_versions(request) self.logger.info("Successfully list_secret_versions👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -1065,7 +1182,7 @@ class DewBlock(SecretBlock): request = ShowSecretVersionRequest() request.secret_name=secret_name request.version_id = version_id - response = self._get_dew_client().cms_client.show_secret_version(request) + response = self.dew_client.cms_client.show_secret_version(request) self.logger.info("Successfully show_secret_version👇") self.logger.info(response) except exceptions.ClientRequestException as e: @@ -1073,6 +1190,7 @@ class DewBlock(SecretBlock): self.logger.error("request_id= %s",e.request_id) self.logger.error("error_code= %s",e.error_code) self.logger.error("error_msg= %s",e.error_msg) + def update_version(self,secret_name=None, version_id=None, expire_time=None,**kwargs): try: request = UpdateVersionRequest() @@ -1081,7 +1199,7 @@ class DewBlock(SecretBlock): request.body = UpdateVersionRequestBody( expire_time=expire_time ) - response = self._get_dew_client().cms_client.update_version(request) + response = self.dew_client.cms_client.update_version(request) self.logger.info("Successfully update_version👇") self.logger.info(response) except exceptions.ClientRequestException as e: diff --git a/prefect_huaweicloud/dew_client.py b/prefect_huaweicloud/dew_client.py index b5e06f2..7aa3751 100644 --- a/prefect_huaweicloud/dew_client.py +++ b/prefect_huaweicloud/dew_client.py @@ -1,30 +1,28 @@ from huaweicloudsdkcore.auth.credentials import BasicCredentials from huaweicloudsdkkms.v2.region.kms_region import KmsRegion -from huaweicloudsdkkms.v2 import * +from huaweicloudsdkkms.v2 import KmsClient from huaweicloudsdkkps.v3.region.kps_region import KpsRegion -from huaweicloudsdkkps.v3 import * +from huaweicloudsdkkps.v3 import KpsClient from huaweicloudsdkcsms.v1.region.csms_region import CsmsRegion -from huaweicloudsdkcsms.v1 import * +from huaweicloudsdkcsms.v1 import CsmsClient + + class DewClient(): - def __init__(self,region_id:str,ak:str,sk:str): + def __init__(self,region_id=None, ak=None, sk=None, *args, **kwargs): + if not ak or not sk: + raise Exception("please input both huawei_cloud_access_key_id and huawei_cloud_secret_access_key") self.region_id=region_id self.__ak=ak self.__sk=sk - @property - def kms_client(self)->KmsClient: - return KmsClient.new_builder() \ + self.kms_client=KmsClient.new_builder() \ .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ .with_region(KmsRegion.value_of(self.region_id)) \ .build() - @property - def kps_client(self)->KpsClient: - return KpsClient.new_builder() \ + self.kps_client=KpsClient.new_builder() \ .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ .with_region(KpsRegion.value_of(self.region_id)) \ .build() - @property - def cms_client(self)->CsmsClient: - return CsmsClient.new_builder() \ + self.cms_client=CsmsClient.new_builder() \ .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ .with_region(CsmsRegion.value_of(self.region_id)) \ .build() diff --git a/prefect_huaweicloud/test/__init__.py b/prefect_huaweicloud/test/__init__.py new file mode 100644 index 0000000..3f591f7 --- /dev/null +++ b/prefect_huaweicloud/test/__init__.py @@ -0,0 +1,3 @@ +from prefect_huaweicloud.obs_block import ObsBlock +from prefect_huaweicloud.dew_block import DewBlock +__all__ = ["ObsBlock","DewBlock"] \ No newline at end of file diff --git a/prefect_huaweicloud/test_dew.py b/prefect_huaweicloud/test/test_dew_block.py similarity index 68% rename from prefect_huaweicloud/test_dew.py rename to prefect_huaweicloud/test/test_dew_block.py index 6c77464..7cf6a7c 100644 --- a/prefect_huaweicloud/test_dew.py +++ b/prefect_huaweicloud/test/test_dew_block.py @@ -1,7 +1,11 @@ +import sys +from pathlib import Path +sys.path.append(str(Path(__file__).resolve().parents[1])) from dew_block import DewBlock from prefect import flow,task -def kms_params(huaweicloud_dew_block,key_alias=None): + +def kms_params(huaweicloud_dew_block, key_alias=None): test_key=huaweicloud_dew_block.create_key(key_alias=key_alias) return dict( key_alias=key_alias, @@ -22,11 +26,12 @@ def kms_params(huaweicloud_dew_block,key_alias=None): "create-datakey", "encrypt-datakey"], grant_id=None, - encryption_algorithm="SYMMETRIC_DEFAULT" + encryption_algorithm="SYMMETRIC_DEFAULT", + rotation_interval=30, ) -def kps_params(huaweicloud_dew_block,name): +def kps_params(huaweicloud_dew_block, name): key_pair_list=huaweicloud_dew_block.list_keypairs() if name in list(x.keypair.name for x in key_pair_list.keypairs[:]): huaweicloud_dew_block.delete_keypair(keypair_name=name) @@ -39,8 +44,9 @@ def kps_params(huaweicloud_dew_block,name): description=None ) + @flow -def test_key_lifecycle_management(kms_params,huaweicloud_dew_block): +def test_key_lifecycle_management(kms_params, huaweicloud_dew_block): row_key_alias=kms_params['key_alias'] huaweicloud_dew_block.create_key(**kms_params) huaweicloud_dew_block.disable_key(**kms_params) @@ -55,8 +61,9 @@ def test_key_lifecycle_management(kms_params,huaweicloud_dew_block): huaweicloud_dew_block.cancel_key_deletion(**kms_params) huaweicloud_dew_block.enable_key(**kms_params) + @flow -def test_data_key_management(kms_params,huaweicloud_dew_block): +def test_data_key_management(kms_params, huaweicloud_dew_block): huaweicloud_dew_block.create_data_key_without_plaintext(**kms_params) create_data_key_response=huaweicloud_dew_block.create_data_key(**kms_params) huaweicloud_dew_block.create_random(**kms_params) @@ -65,10 +72,10 @@ def test_data_key_management(kms_params,huaweicloud_dew_block): kms_params["datakey_dgst"]=decrypt_data_key_response.datakey_dgst kms_params["plain_text"]=decrypt_data_key_response.data_key+decrypt_data_key_response.datakey_dgst huaweicloud_dew_block.encrypt_data_key(**kms_params) - + @flow -def test_key_grant_management(kms_params,huaweicloud_dew_block): +def test_key_grant_management(kms_params, huaweicloud_dew_block): create_grant_response=huaweicloud_dew_block.create_grant(**kms_params) kms_params["grant_id"]=create_grant_response.grant_id huaweicloud_dew_block.list_retirable_grants(**kms_params) @@ -77,11 +84,8 @@ def test_key_grant_management(kms_params,huaweicloud_dew_block): huaweicloud_dew_block.list_grants(**kms_params) - - - @flow -def test_key_pair_management(kps_params,huaweicloud_dew_block): +def test_key_pair_management(kps_params, huaweicloud_dew_block): row_keypair_name=kps_params['name'] huaweicloud_dew_block.import_private_key(**kps_params) huaweicloud_dew_block.export_private_key(**kps_params) @@ -93,18 +97,39 @@ def test_key_pair_management(kps_params,huaweicloud_dew_block): huaweicloud_dew_block.delete_keypair(**kps_params) -def test_small_data_encryption(kms_params,huaweicloud_dew_block): + +@flow +def test_small_data_encryption(kms_params, huaweicloud_dew_block): encrypt_data_response=huaweicloud_dew_block.encrypt_data(**kms_params) kms_params["cipher_text"]=encrypt_data_response.cipher_text huaweicloud_dew_block.decrypt_data(**kms_params) + +@flow +def test_list_key(kms_params, huaweicloud_dew_block): + huaweicloud_dew_block.list_keys(**kms_params) + huaweicloud_dew_block.list_key_detail(**kms_params) + huaweicloud_dew_block.show_public_key(key_id="029c2ea1-196d-47a4-b377-ac8bb359b344") + huaweicloud_dew_block.show_user_instances(**kms_params) + huaweicloud_dew_block.show_user_quotas(**kms_params) + + +@flow +def key_rotation_management(kms_params, huaweicloud_dew_block): + huaweicloud_dew_block.enable_key_rotation(**kms_params) + huaweicloud_dew_block.show_key_rotation_status(**kms_params) + huaweicloud_dew_block.update_key_rotation_interval(**kms_params) + huaweicloud_dew_block.disable_key_rotation(**kms_params) + if __name__=="__main__": huaweicloud_dew_block = DewBlock.load("test-dew-block") - kms_params=kms_params(huaweicloud_dew_block,key_alias="12-26") -# test_key_lifecycle_management(kms_params,huaweicloud_dew_block) -# test_key_pair_management(kps_params(huaweicloud_dew_block,name="22-22"),huaweicloud_dew_block) + kms_params=kms_params(huaweicloud_dew_block, key_alias="12-26") + test_key_lifecycle_management(kms_params,huaweicloud_dew_block) + test_key_pair_management(kps_params(huaweicloud_dew_block,name="22-22"),huaweicloud_dew_block) test_data_key_management(kms_params,huaweicloud_dew_block) -# test_key_grant_management(kms_params,huaweicloud_dew_block) + test_key_grant_management(kms_params,huaweicloud_dew_block) test_small_data_encryption(kms_params,huaweicloud_dew_block) + test_list_key(kms_params, huaweicloud_dew_block) + key_rotation_management(kms_params, huaweicloud_dew_block) \ No newline at end of file -- Gitee From 23c73c684243818a448a44605200b6e614bf7d18 Mon Sep 17 00:00:00 2001 From: lky0312 <523175094@qq.com> Date: Fri, 19 Jan 2024 03:01:28 +0800 Subject: [PATCH 03/11] 24-1-19 Supplementary methods and correction of code style --- prefect_huaweicloud/dew_block.py | 2345 ++++++++++++++------ prefect_huaweicloud/dew_client.py | 14 +- prefect_huaweicloud/test/test_dew_block.py | 255 ++- 3 files changed, 1907 insertions(+), 707 deletions(-) diff --git a/prefect_huaweicloud/dew_block.py b/prefect_huaweicloud/dew_block.py index 83feb0f..307f3ca 100644 --- a/prefect_huaweicloud/dew_block.py +++ b/prefect_huaweicloud/dew_block.py @@ -1,9 +1,7 @@ - -from typing import Any, Dict, List, Optional, Union +from typing import Optional from logging import Logger from pydantic import Field, SecretStr from prefect.blocks.abstract import Block -from prefect.utilities.asyncutils import run_sync_in_worker_thread, sync_compatible from prefect.logging.loggers import get_logger, get_run_logger from prefect.exceptions import MissingContextError from prefect import task @@ -27,30 +25,30 @@ class DewBlock(Block): _documentation_url = ("https://support.huaweicloud.com/intl/zh-cn/sdk-python-devg-obs/obs_22_0100.html") # noqa huawei_cloud_access_key_id: Optional[SecretStr] = Field( - default=None, - description="A specific Huawei Cloud access key ID.", - title="Huawei Cloud Access Key ID:", + default = None, + description = "A specific Huawei Cloud access key ID.", + title = "Huawei Cloud Access Key ID:", ) huawei_cloud_secret_access_key: Optional[SecretStr] = Field( - default=None, - description="A specific Huawei Cloud secret access key.", - title="Huawei Cloud Access Key Secret:", + default = None, + description = "A specific Huawei Cloud secret access key.", + title = "Huawei Cloud Access Key Secret:", ) huawei_cloud_security_token: Optional[SecretStr] = Field( - default=None, - description="SecurityToken in the temporary access key, " + default = None, + description = "SecurityToken in the temporary access key, " "You can select a temporary token or AK/SK for authentication", - title="Huawei Cloud Security Token", + title = "Huawei Cloud Security Token", ) region_id:Optional[str] = Field( - default=None, - title="region id", + default = None, + title = "region id", ) - def __init__(self,*args,**kwargs): - self.dew_client=DewClient(region_id=kwargs['region_id'], - ak=kwargs['huawei_cloud_access_key_id'], - sk=kwargs['huawei_cloud_secret_access_key']) + def __init__(self, *args, **kwargs): + self.dew_client = DewClient(region_id = kwargs['region_id'], + ak = kwargs['huawei_cloud_access_key_id'], + sk = kwargs['huawei_cloud_secret_access_key']) @property def logger(self) -> Logger: @@ -68,1144 +66,2199 @@ class DewBlock(Block): except MissingContextError: return get_logger(self.__class__.__name__) - def create_key(self,key_alias=None, key_spec=None, key_usage=None, key_description=None, - origin=None, enterprise_project_id=None, sequence=None, keystore_id=None,**kwargs): + def create_key(self, key_alias = None, key_spec = None, key_usage = None, key_description = None, + origin = None, enterprise_project_id = None, sequence = None, keystore_id = None, **kwargs): + """ + Create a user master key, which can be a symmetric or asymmetric key. + + Args: + Key_ Alias: Non default master key alias, with a value range of 1 to 255 characters, satisfying + regular matching "^ [a-zA-Z0-9:/_ -] {1255} $", and not having the same name as the default + master key alias created by the system service. + type key_alias: str + """ try: request = CreateKeyRequest() request.body = CreateKeyRequestBody( - key_alias=key_alias, - key_spec=key_spec, - key_usage=key_usage, - key_description=key_description, - origin=origin, - enterprise_project_id=enterprise_project_id, - sequence=sequence, - keystore_id=keystore_id + key_alias = key_alias, + key_spec = key_spec, + key_usage = key_usage, + key_description = key_description, + origin = origin, + enterprise_project_id = enterprise_project_id, + sequence = sequence, + keystore_id = keystore_id ) - response =self.dew_client.kms_client.create_key(request) + response = self.dew_client.kms_client.create_key(request) self.logger.debug("Created key") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def delete_key(self,key_id=None,pending_days=None, sequence=None,**kwargs): + def delete_key(self, key_id = None, pending_days = None, sequence = None, **kwargs): + """ + How many days do you plan to delete the key? The key can be deleted within 7-1096 days. + + Args: + key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + :pending_days: How many days do you plan to delete the key, with values ranging from 7 to 1096. + :type pending_days: str + """ try: request = DeleteKeyRequest() request.body = ScheduleKeyDeletionRequestBody( - key_id=key_id, - pending_days=pending_days, - sequence=sequence + key_id = key_id, + pending_days = pending_days, + sequence = sequence ) response = self.dew_client.kms_client.delete_key(request) self.logger.debug("Successfully delete_key") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def disable_key(self,key_id=None,sequence=None,**kwargs): + def disable_key(self, key_id = None, sequence = None, **kwargs): + """ + Disabled key, cannot be used after disabling the key. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + """ try: request = DisableKeyRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) - response =self.dew_client.kms_client.disable_key(request) - self.logger.info("Successfully disable_key👇") + response = self.dew_client.kms_client.disable_key(request) + self.logger.info("Successfully disable_key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def enable_key(self,key_id=None, sequence=None,**kwargs): + def enable_key(self, key_id = None, sequence = None, **kwargs): + """ + Enable the key, which can only be used after it is enabled. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + """ try: request = EnableKeyRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) - response =self.dew_client.kms_client.enable_key(request) - self.logger.info("Successfully enable_key👇") + response = self.dew_client.kms_client.enable_key(request) + self.logger.info("Successfully enable_key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def update_key_Alias(self,key_id=None, key_alias=None, sequence=None,**kwargs): + def update_key_Alias(self, key_id = None, key_alias = None, sequence = None, **kwargs): + """ + Modify the user master key alias + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + :key_alias: Non default master key alias, ranging from 1 to 255 characters, satisfies regular matching + "^[a-zA-Z0-9:/_-]{1,255}$"and cannot have the suffix "/default". + :type key_alias: str + """ try: request = UpdateKeyAliasRequest() request.body = UpdateKeyAliasRequestBody( - key_alias=key_alias, - key_id=key_id, - sequence=sequence + key_alias = key_alias, + key_id = key_id, + sequence = sequence ) - response =self.dew_client.kms_client.update_key_alias(request) + response = self.dew_client.kms_client.update_key_alias(request) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def update_key_description(self,key_id=None, key_description=None, sequence=None,**kwargs): + def update_key_description(self, key_id = None, key_description = None, sequence = None, **kwargs): + """ + Modify user master key description information. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + :key_description: Key description, ranging from 0 to 255 characters. + :type key_description: str + """ try: request = UpdateKeyDescriptionRequest() request.body = UpdateKeyDescriptionRequestBody( - key_id=key_id, - key_description=key_description, - sequence=sequence + key_id = key_id, + key_description = key_description, + sequence = sequence ) - response =self.dew_client.kms_client.update_key_description(request) - self.logger.info("Successfully update_key_description👇") + response = self.dew_client.kms_client.update_key_description(request) + self.logger.info("Successfully update_key_description:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def cancel_key_deletion(self,key_id=None,sequence=None,**kwargs): + def cancel_key_deletion(self, key_id = None, sequence = None, **kwargs): + """ + Cancel plan to delete key. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + """ try: request = CancelKeyDeletionRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.cancel_key_deletion(request) - self.logger.info("Successfully canccel key daletion👇") + self.logger.info("Successfully canccel key daletion:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_data_key(self,key_id,key_spec=None, datakey_length=None, sequence=None,**kwargs): + def create_data_key(self, key_id, key_spec = None, datakey_length = None, sequence = None, **kwargs): + """ + Create a data key and return a result containing both plaintext and ciphertext. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + """ try: request = CreateDatakeyRequest() request.body = CreateDatakeyRequestBody( - key_id=key_id, - key_spec=key_spec, - datakey_length=datakey_length, - sequence=sequence + key_id = key_id, + key_spec = key_spec, + datakey_length = datakey_length, + sequence = sequence ) response = self.dew_client.kms_client.create_datakey(request) - self.logger.info("Successfully created datakey👇") + self.logger.info("Successfully created datakey:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_data_key_without_plaintext(self,key_id,key_spec=None, datakey_length=None, sequence=None,**kwargs): + def create_data_key_without_plaintext(self, key_id, key_spec = None, datakey_length = None, sequence = None, **kwargs): + """ + Create a data key and return a result that only contains ciphertext. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + """ try: request = CreateDatakeyWithoutPlaintextRequest() request.body = CreateDatakeyRequestBody( - key_id=key_id, - key_spec=key_spec, - datakey_length=datakey_length, - sequence=sequence + key_id = key_id, + key_spec = key_spec, + datakey_length = datakey_length, + sequence = sequence ) response = self.dew_client.kms_client.create_datakey_without_plaintext(request) - self.logger.info("Successfully created datakey without plaintext👇") + self.logger.info("Successfully created datakey without plaintext:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_random(self,random_data_length=None, sequence=None,**kwargs): + def create_random(self, random_data_length = None, sequence = None, **kwargs): + """ + Generate random numbers within the range of 8-8192 bits. + + Args: + :param random_ Data_ Length: The bit length of a random number. The value is a multiple of 8, with a range of 8 to 8192. + The bit length of a random number, with a value of 512. + :type random_ Data_ Length: str + """ try: request = CreateRandomRequest() request.body = GenRandomRequestBody( - random_data_length=random_data_length, - sequence=sequence + random_data_length = random_data_length, + sequence = sequence ) response = self.dew_client.kms_client.create_random(request) - self.logger.info("Successfully created random👇") + self.logger.info("Successfully created random:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def decrypt_data_key(self,key_id=None, cipher_text=None, datakey_cipher_length=None, sequence=None,**kwargs): + def decrypt_data_key(self, key_id = None, cipher_text = None, datakey_cipher_length = None, sequence = None, **kwargs): + """ + Decrypt data key, decrypt data key with specified master key. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + + :cipher_text: The hexadecimal string of DEK ciphertext and metadata. + The value is the cipher in the encrypted data key result_ The value of text. + :type cipher_text: str + + :datakey_cipher_length: The key byte length, with a range of 1 to 1024. Key byte length, with a value of "64". + :type datakey_cipher_length: str + """ try: request = DecryptDatakeyRequest() request.body = DecryptDatakeyRequestBody( - key_id=key_id, - cipher_text=cipher_text, - datakey_cipher_length=datakey_cipher_length, - sequence=sequence + key_id = key_id, + cipher_text = cipher_text, + datakey_cipher_length = datakey_cipher_length, + sequence = sequence ) response = self.dew_client.kms_client.decrypt_datakey(request) - self.logger.info("Successfully decrypted datakey👇") + self.logger.info("Successfully decrypted datakey:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def encrypt_data_key(self,key_id=None, plain_text=None, datakey_plain_length=None, sequence=None,**kwargs): + def encrypt_data_key(self, key_id = None, plain_text = None, datakey_plain_length = None, sequence = None, **kwargs): + """ + Encrypt the data key with the specified master key. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + + :param plain_ Text: When CMK is AES, SHA256 (32 bytes) for DEK plaintext and DEK plaintext; When CMK is SM4, + both DEK plaintext and SM3 (32 bytes) of DEK plaintext are represented as hexadecimal strings. + :type plain_ Text: str + + :param datakey_ Plain_ Length: DEK plaintext byte length, with a range of 1 to 1024. DEK plaintext byte length, with a value of "64". + :type datakey_ Plain_ Length: str + """ try: request = EncryptDatakeyRequest() request.body = EncryptDatakeyRequestBody( - key_id=key_id, - plain_text=plain_text, - datakey_plain_length=datakey_plain_length, - sequence=sequence + key_id = key_id, + plain_text = plain_text, + datakey_plain_length = datakey_plain_length, + sequence = sequence ) response = self.dew_client.kms_client.encrypt_datakey(request) - self.logger.info("Successfully encrypted datakey👇") + self.logger.info("Successfully encrypted datakey:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_parameters_for_import(self,key_id,wrapping_algorithm=None, sequence=None,**kwargs): + def create_parameters_for_import(self, key_id,wrapping_algorithm = None, sequence = None, **kwargs): + """ + Obtain the necessary parameters for importing keys, including key import tokens and key encryption public keys. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + :wrapping_algorithm: Key material encryption algorithm, enumeration as follows: - RSAES_ OAEP_ SHA_ 256- SM2_ ENCRYPT, + some offices do not support this import type + :type wrapping_ algorithm: str + """ try: request = CreateParametersForImportRequest() request.body = GetParametersForImportRequestBody( - key_id=key_id, - wrapping_algorithm=wrapping_algorithm, - sequence=sequence + key_id = key_id, + wrapping_algorithm = wrapping_algorithm, + sequence = sequence ) response = self.dew_client.kms_client.create_parameters_for_import(request) - self.logger.info("Successfully created parameters for import👇") + self.logger.info("Successfully created parameters for import:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def delete_imported_key_material(self,key_id,sequence=None,**kwargs): + def delete_imported_key_material(self, key_id, sequence = None, **kwargs): + """ + Delete key material information. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + """ try: request = DeleteImportedKeyMaterialRequest() request.body = OperateKeyRequestBody( key_id = key_id, - sequence=sequence + sequence = sequence ) response = self.dew_client.kms_client.delete_imported_key_material(request) - self.logger.info("Successfully deleted imported key material👇") + self.logger.info("Successfully deleted imported key material:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def import_key_material(self,key_id=None, import_token=None, - encrypted_key_material=None, encrypted_privatekey=None, - expiration_time=None, sequence=None, **kwargs): + def import_key_material(self, key_id = None, import_token = None, + encrypted_key_material = None, encrypted_privatekey = None, + expiration_time = None, sequence = None, **kwargs): + """ + Import key materials. + + Args: + : param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param import_token: Key import token, in base64 format, that satisfies regular matching "^[0-9a-zA-Z+/=]{200,6144}$". + :type import_ Token: str + + :param encrypted_key_material: The encrypted symmetric key material, in base64 format, satisfies regular matching + "^[0-9a-zA-Z+/=]{344,360}$". If importing an asymmetric key, this parameter is the temporary intermediate key used to encrypt the private key. + :type encrypted_key_material: str + """ try: request = ImportKeyMaterialRequest() request.body = ImportKeyMaterialRequestBody( - key_id=key_id, - import_token=import_token, - encrypted_key_material=encrypted_key_material, - encrypted_privatekey=encrypted_privatekey, - expiration_time=expiration_time, - sequence=sequence + key_id = key_id, + import_token = import_token, + encrypted_key_material = encrypted_key_material, + encrypted_privatekey = encrypted_privatekey, + expiration_time = expiration_time, + sequence = sequence ) response = self.dew_client.kms_client.import_key_material(request) - self.logger.info("Successfully imported key material👇") + self.logger.info("Successfully imported key material:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_grant(self,key_id=None, grantee_principal=None, listOperationsbody=[], - name=None, retiring_principal=None, grantee_principal_type=None, sequence=None,**kwargs): + def create_grant(self, key_id = None, grantee_principal = None, listOperationsbody = None, + name = None, retiring_principal = None, grantee_principal_type = None, sequence = None, **kwargs): + """ + Create authorization, authorized users can operate on the authorization key. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param grantee_principal:Authorized user ID, 1~64 bytes, satisfies regular matching "^[a-zA-Z0-9]{1,64}$". + For example:0d0466b00d0466b00d0466b00d0466b0 + :type grantee_principal: str + + :param operations: List of authorized and allowed operations. Valid values: "create datakey", "create datakey without plaintext", + "encrypt datakey", "decrypt datakey", "describe key", "create grant", "retain grant", "encrypt data", "decrypt data". The valid + values cannot be just "create grant"- "Create datakey" Create data key - "Create datakey without plaintext" Create data key without + plaintext - "encrypt datakey" Encrypt data key - "decrypt datakey" Decrypt data key - "describe key" Query key information - + "retain grant" Retirement authorization - "encrypt data" Encrypt data - "decrypt data" Decrypt data + :type operations: list[str] + """ try: - request = CreateGrantRequest() - + request = CreateGrantRequest() request.body = CreateGrantRequestBody( - key_id=key_id, - grantee_principal=grantee_principal, - operations=listOperationsbody, - grantee_principal_type=grantee_principal_type, - retiring_principal=retiring_principal, - name=name, - sequence=sequence + key_id = key_id, + grantee_principal = grantee_principal, + operations = listOperationsbody, + grantee_principal_type = grantee_principal_type, + retiring_principal = retiring_principal, + name = name, + sequence = sequence ) response = self.dew_client.kms_client.create_grant(request) - self.logger.info("Successfully create grant👇") + self.logger.info("Successfully create grant:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(e.status_code) - self.logger.error(e.request_id) - self.logger.error(e.error_code) - self.logger.error(e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_retirable_grants(self,limit=None, marker=None, sequence=None, **kwargs): + def list_retirable_grants(self, limit = None, marker = None, sequence = None, **kwargs): + """ + Query the list of authorizations that users can retire from. + """ try: request = ListRetirableGrantsRequest() request.body = ListRetirableGrantsRequestBody( - limit=limit, - marker=marker, - sequence=sequence + limit = limit, + marker = marker, + sequence = sequence ) response = self.dew_client.kms_client.list_retirable_grants(request) - self.logger.info("Successfully list retirable grants👇") + self.logger.info("Successfully list retirable grants:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(e.status_code) - self.logger.error(e.request_id) - self.logger.error(e.error_code) - self.logger.error(e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_grants(self,key_id=None, limit=None, marker=None, sequence=None,**kwargs): + def list_grants(self, key_id = None, limit = None, marker = None, sequence = None, **kwargs): + """ + Authorization list for querying keys + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + """ try: request = ListGrantsRequest() request.body = ListGrantsRequestBody( - key_id=key_id, - limit=limit, - marker=marker, - sequence=sequence + key_id = key_id, + limit = limit, + marker = marker, + sequence = sequence ) response = self.dew_client.kms_client.list_grants(request) - self.logger.info("Successfully list grants👇") + self.logger.info("Successfully list grants:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(e.status_code) - self.logger.error(e.request_id) - self.logger.error(e.error_code) - self.logger.error(e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def cancel_self_grant(self,key_id=None, grant_id=None, sequence=None,**kwargs): + def cancel_self_grant(self, key_id = None, grant_id = None, sequence = None, **kwargs): + """ + Retirement authorization means that the authorized user no longer has the right to operate the authorization key. + For example, if user A authorizes user B to operate key A/key, and authorizes user C to revoke the authorization, + then users A, B, and C can all retire the authorization. After retiring the authorization, user B can no longer use key A. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param grant_id: Authorization ID, 64 bytes, satisfies regular matching "^[A-Fa-f0-9]{64}$". + For example:7c9a3286af4fcca5f0a385ad13e1d21a50e27b6dbcab50f37f30f93b8939827d + :type grant_id: str + """ try: request = CancelSelfGrantRequest() request.body = RevokeGrantRequestBody( - grant_id=grant_id, - key_id=key_id, - sequence=sequence + grant_id = grant_id, + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.cancel_self_grant(request) - self.logger.info("Successfully cancel self grant👇") + self.logger.info("Successfully cancel self grant:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(e.status_code) - self.logger.error(e.request_id) - self.logger.error(e.error_code) - self.logger.error(e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def cancel_grant(self,key_id=None, grant_id=None, sequence=None,**kwargs): + def cancel_grant(self, key_id = None, grant_id = None, sequence = None, **kwargs): + """ + Revoke authorization, authorize the user to revoke the authorized user's permission to operate the key + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param grant_id: Authorization ID, 64 bytes, satisfies regular matching "^[A-Fa-f0-9]{64}$". + For example:7c9a3286af4fcca5f0a385ad13e1d21a50e27b6dbcab50f37f30f93b8939827d + :type grant_id: str + """ try: request = CancelGrantRequest() request.body = RevokeGrantRequestBody( - grant_id=grant_id, - key_id=key_id, - sequence=sequence + grant_id = grant_id, + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.cancel_grant(request) - self.logger.info("Successfully cancel grant👇") + self.logger.info("Successfully cancel grant:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(e.status_code) - self.logger.error(e.request_id) - self.logger.error(e.error_code) - self.logger.error(e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + def decrypt_data(self, cipher_text = None, encryption_algorithm = None, key_id = None, sequence = None, **kwargs): + """ + Decrypting data. + + Args: + :param cipher_text: Encrypted data ciphertext. The value is the cipher in the encrypted data result. + The value of text satisfies regular matching "^[0-9a-zA-Z+/=]{128,5648}$". + :type cipher_text: str - def decrypt_data(self,cipher_text=None, encryption_algorithm=None, key_id=None, sequence=None,**kwargs): + """ try: request = DecryptDataRequest() request.body = DecryptDataRequestBody( - cipher_text=cipher_text, - encryption_algorithm=encryption_algorithm, - key_id=key_id, - sequence=sequence + cipher_text = cipher_text, + encryption_algorithm = encryption_algorithm, + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.decrypt_data(request) - self.logger.info("Successfully decrypted data👇") + self.logger.info("Successfully decrypted data:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def encrypt_data(self,key_id=None,plain_text=None, encryption_algorithm=None, sequence=None,**kwargs): + def encrypt_data(self, key_id = None,plain_text = None, encryption_algorithm = None, sequence = None, **kwargs): + """ + Encrypt data using the specified user master key. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param plain_text: Clear text data, 1-4096 bytes, satisfies regular matching + "^.{14096}$", and the length range after converting to a byte array is 1-4096 bytes.. + :type plain_text: str + """ try: request = EncryptDataRequest() request.body = EncryptDataRequestBody( - plain_text=plain_text, - key_id=key_id, - encryption_algorithm=encryption_algorithm, - sequence=sequence + plain_text = plain_text, + key_id = key_id, + encryption_algorithm = encryption_algorithm, + sequence = sequence ) response = self.dew_client.kms_client.encrypt_data(request) - self.logger.info("Successfully encrypted data👇") + self.logger.info("Successfully encrypted data:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_key_detail(self,key_id=None,sequence=None,**kwargs): + def sign(self, key_id = None, message = None, signing_algorithm = None, message_type = None, sequence = None, **kwargs): + """ + Digitally sign a message or message digest using a private key with an asymmetric key. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param signing_algorithm: The signature algorithm is listed as follows: + - RSASSA_PSS_SHA_256 - RSASSA_PSS_SHA_384 - RSASSA_PSS_SHA_512 - RSASSA_PKCS1_V1_5_SHA_256 + - RSASSA_PKCS1_V1_5_SHA_384 - RSASSA_PKCS1_V1_5_SHA_512 - ECDSA_SHA_256 - ECDSA_SHA_384 + - ECDSA_SHA_512 - SM2DSA_SM3 + :type signing_algorithm: str + + :param message: The message digest or message to be signed must have a message length of less than 4096 bytes and be encoded using Base64. + :type message: str + """ + try: + request = SignRequest() + request.body = SignRequestBody( + signing_algorithm = signing_algorithm, + message = message, + key_id = key_id, + message_type = message_type, + sequence = sequence + ) + response = self.dew_client.kms_client.sign(request) + self.logger.info("Successfully sign:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def validate_signature(self, key_id = None, message = None, signature = None, signing_algorithm = None, + message_type = None, sequence = None, **kwargs): + """ + Verify the signature of a message or message digest using a public key with an asymmetric key. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param signing_algorithm: The signature algorithm is listed as follows: + - RSASSA_PSS_SHA_256 - RSASSA_PSS_SHA_384 - RSASSA_PSS_SHA_512 - RSASSA_PKCS1_V1_5_SHA_256 + - RSASSA_PKCS1_V1_5_SHA_384 - RSASSA_PKCS1_V1_5_SHA_512 - ECDSA_SHA_256 - ECDSA_SHA_384 + - ECDSA_SHA_512 - SM2DSA_SM3 + :type signing_algorithm: str + + :param message: The message digest or message to be signed must have a message length of less than 4096 bytes and be encoded using Base64. + :type message: str + + :param signature: The signature value to be verified is encoded using Base64. + :type signature: str + """ + try: + request = ValidateSignatureRequest() + request.body = VerifyRequestBody( + key_id = key_id, + message = message, + signature = signature, + signing_algorithm = signing_algorithm, + message_type = message_type, + sequence = sequence + ) + response = self.dew_client.kms_client.validate_signature(request) + self.logger.info("Successfully list validate signature:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def list_key_detail(self, key_id = None,sequence = None, **kwargs): + """ + Query key details. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + """ try: request = ListKeyDetailRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.list_key_detail(request) - self.logger.info("Successfully list key detail👇") + self.logger.info("Successfully list key detail:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_keys(self,limit=None, marker=None, key_state=None, key_spec=None, - enterprise_project_id=None, sequence=None,**kwargs): + def list_keys(self,limit = None, marker = None, key_state = None, key_spec = None, + enterprise_project_id = None, sequence = None, **kwargs): + """ + Query the list of all user keys. + """ try: request = ListKeysRequest() request.body = ListKeysRequestBody( - limit=limit, - marker=marker, - key_state=key_state, - key_spec=key_spec, - enterprise_project_id=enterprise_project_id, - sequence=sequence + limit = limit, + marker = marker, + key_state = key_state, + key_spec = key_spec, + enterprise_project_id = enterprise_project_id, + sequence = sequence ) - response = self.dew_client.kms_client.list_keys(request) - # self.logger.error(response.to_dict()) - self.logger.error(json.dumps(response.to_dict()).replace('}','}\n')) + response = self.dew_client.kms_client.list_keys(request) + self.logger.info(json.dumps(response.to_dict()).replace('}','}\n')) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_public_key(self,key_id=None, sequence=None,**kwargs): + def show_public_key(self, key_id = None, sequence = None, **kwargs): + """ + Query public key information for user specified asymmetric keys. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + """ try: request = ShowPublicKeyRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.show_public_key(request) - self.logger.info("Successfully show public key👇") + self.logger.info("Successfully show public key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_user_instances(self,**kwargs): + def show_user_instances(self, **kwargs): + """ + Query the number of instances to obtain the number of user master keys that have already been created by the user + """ try: request = ShowUserInstancesRequest() response = self.dew_client.kms_client.show_user_instances(request) - self.logger.info("Successfully show user instances👇") + self.logger.info("Successfully show user instances:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_user_quotas(self,**kwargs): + def show_user_quotas(self, **kwargs): + """ + Query quotas, query the total number of user master key quotas that users can create and current usage information. + """ try: request = ShowUserQuotasRequest() response = self.dew_client.kms_client.show_user_quotas(request) - self.logger.info("Successfully show user quotas👇") + self.logger.info("Successfully show user quotas:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_version(self, **kwargs): + def show_version(self,version_id = None, **kwargs): + """ + Check the specified API version information + + Args: + :param version_id: API version number + :type version_id: str + """ try: - request = ShowVersionRequest(kwargs) + request = ShowVersionRequest(version_id = version_id) response = self.dew_client.kms_client.show_version(request) - self.logger.info("Successfully show_version👇") + self.logger.info("Successfully show_version:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_versions(self,**kwargs): + def show_versions(self, **kwargs): + """ + Query API version information list. + """ try: request = ShowVersionsRequest() response = self.dew_client.kms_client.show_versions(request) - self.logger.info("Successfully show versions👇") + self.logger.info("Successfully show versions:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(e) + + def disable_key_rotation(self, key_id = None, sequence = None, **kwargs): + """ + Turn off user master key rotation. - def disable_key_rotation(self, key_id=None, sequence=None, **kwargs): + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + """ try: request = DisableKeyRotationRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.disable_key_rotation(request) - self.logger.info("Successfully disable key rotation👇") + self.logger.info("Successfully disable key rotation:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def enable_key_rotation(self, key_id=None, sequence=None, **kwargs): + def enable_key_rotation(self, key_id = None, sequence = None, **kwargs): + """ + Enable user master key rotation. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + """ try: request = EnableKeyRotationRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.enable_key_rotation(request) - self.logger.info("Successfully enable key rotation👇") + self.logger.info("Successfully enable key rotation:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def show_key_rotation_status(self, key_id = None, sequence = None, **kwargs): + """ + Query user master key rotation status - def show_key_rotation_status(self, key_id=None, sequence=None, **kwargs): + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + """ try: request = ShowKeyRotationStatusRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.show_key_rotation_status(request) - self.logger.info("Successfully show key rotation status👇") + self.logger.info("Successfully show key rotation status:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def update_key_rotation_interval(self, key_id=None, rotation_interval=None, sequence=None, **kwargs): + def update_key_rotation_interval(self, key_id = None, rotation_interval = None, sequence = None, **kwargs): + """ + Modify the user master key rotation cycle. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param rotation_interval: Rotation period, an integer with a range of values from 30 to 365. + The cycle range is set based on the frequency of key usage. If the frequency of key usage is high, + it is recommended to set it to a short cycle; On the contrary, set it to long cycle. + :type rotation_interval: int + """ try: request = UpdateKeyRotationIntervalRequest() request.body = UpdateKeyRotationIntervalRequestBody( - rotation_interval=rotation_interval, - key_id=key_id, - sequence=sequence + rotation_interval = rotation_interval, + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.update_key_rotation_interval(request) - self.logger.info("Successfully update key rotation interval👇") + self.logger.info("Successfully update key rotation interval:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def create_keypair(self,name = None, type = None, public_key = None, scope = None, user_id = None, key_protection = None, **kwargs): + """ + Create and import SSH key pairs. - def create_keypair(self,name=None, type=None, public_key=None, scope=None, user_id=None, key_protection=None, **kwargs): + Args: + :param name: The name of the SSH key pair.-The name of a newly created key pair cannot be the same as the name of an existing key pair. + - The SSH key pair name consists of English letters, numbers, underscores, and midlines, and the length cannot exceed 64 bytes + :type name: str + """ try: request = CreateKeypairRequest() - keypairbody = CreateKeypairAction( - name=name, - type=type, - public_key=public_key, - scope=scope, - user_id=user_id, - key_protection=key_protection + key_pair_body = CreateKeypairAction( + name = name, + type = type, + public_key = public_key, + scope = scope, + user_id = user_id, + key_protection = key_protection ) request.body = CreateKeypairRequestBody( - keypair=keypairbody + keypair = key_pair_body ) response = self.dew_client.kps_client.create_keypair(request) - self.logger.info("Successfully created keypair👇") + self.logger.info("Successfully created keypair:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_keypairs(self,limit=None, marker=None,**kwargs): + def list_keypairs(self,limit = None, marker = None, **kwargs): + """ + Query SSH key pair list. + """ try: - request = ListKeypairsRequest( - limit=limit, - marker=marker - ) + request = ListKeypairsRequest(limit = limit, marker = marker) response = self.dew_client.kps_client.list_keypairs(request) - self.logger.info("Successfully list keypairs👇") + self.logger.info("Successfully list keypairs:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def clear_private_key(self,keypair_name=None,**kwargs): + def clear_private_key(self, keypair_name = None, **kwargs): + """ + Clear SSH key pair private key + + Args: + :param keypair_name: Key pair name. + :type keypair_name: str + """ try: - request = ClearPrivateKeyRequest(keypair_name=keypair_name) + request = ClearPrivateKeyRequest(keypair_name = keypair_name) response = self.dew_client.kps_client.clear_private_key(request) - self.logger.info("Successfully cleared private key👇") + self.logger.info("Successfully cleared private key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def import_private_key(self,user_id=None, name=None,type="default",kms_key_name="kps/default",private_key=None,**kwargs): + def import_private_key(self, user_id = None, name = None,type = "default", kms_key_name = "kps/default", private_key = None, **kwargs): + """ + Import the private key into the specified key pair. + + Args: + :param name: The name of the SSH key pair.- The name of a newly created key pair cannot be the same as the name of an existing key pair. + - The SSH key pair name consists of English letters, numbers, underscores, and midlines, and the length cannot exceed 64 bytes + :type name: str + + :param private_key: Import the private key of an SSH key pair. + :type private_key: str + + :param type: 取值范围: "kms" or "default"- "Default" is the default encryption method, suitable for offices without KMS services. + - "KMS" refers to the use of KMS service encryption method. If the station does not have KMS service, please fill in "default". + :type type: str + + :param kms_key_name: The name of the KMS key.- If "type" is "kms", the kms service key name must be filled in. + :type kms_key_name: str + """ try: request = ImportPrivateKeyRequest() - encryptionKeyProtection = Encryption( - type=type, - kms_key_name=kms_key_name - ) - keyProtectionKeypair = ImportPrivateKeyProtection( - private_key=private_key, - encryption=encryptionKeyProtection + encryption_key_protection = Encryption( + type = type, + kms_key_name = kms_key_name ) - keypairbody = ImportPrivateKeyKeypairBean( - name=name, - key_protection=keyProtectionKeypair, - user_id=user_id + key_protection_keypair = ImportPrivateKeyProtection( + private_key = private_key, + encryption = encryption_key_protection ) - request.body = ImportPrivateKeyRequestBody( - keypair=keypairbody + key_pair_body = ImportPrivateKeyKeypairBean( + name = name, + key_protection = key_protection_keypair, + user_id = user_id ) + request.body = ImportPrivateKeyRequestBody(keypair = key_pair_body) response = self.dew_client.kps_client.import_private_key(request) - self.logger.info("Successfully import_private_key👇") + self.logger.info("Successfully import_private_key:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_keypair_detail(self,keypair_name=None,**kwargs): + def list_keypair_detail(self, keypair_name = None, **kwargs): + """ + Query SSH key pair details + + Args: + :param keypair_name: Key pair name. + :type keypair_name: str + """ try: - request = ListKeypairDetailRequest(keypair_name=keypair_name) + request = ListKeypairDetailRequest(keypair_name = keypair_name) response = self.dew_client.kps_client.list_keypair_detail(request) - self.logger.info("Successfully exported private key👇") + self.logger.info("Successfully list private key detail:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def list_keypairs(self, **kwargs): + """ + Query SSH key pair list + """ + try: + request = ListKeypairsRequest() + response = self.dew_client.kps_client.list_keypairs(request) + self.logger.info("Successfully list private keys:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def update_keypair_description(self,keypair_name=None,description=None,**kwargs): + def update_keypair_description(self, keypair_name = None, description = None, **kwargs): + """ + Update SSH key pair description. + + Args: + :param keypair_name: Key pair name. + :type keypair_name: str + + :param description: Descriptive information + :type description: str + """ try: request = UpdateKeypairDescriptionRequest( - keypair_name=keypair_name + keypair_name = keypair_name ) - keypairbody = UpdateKeypairDescriptionReq( - description=description + key_pair_body = UpdateKeypairDescriptionReq( + description = description ) request.body = UpdateKeypairDescriptionRequestBody( - keypair=keypairbody + keypair = key_pair_body ) response = self.dew_client.kps_client.update_keypair_description(request) - self.logger.info("Successfully updated👇") + self.logger.info("Successfully update keypair description:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def export_private_key(self,name=None,**kwargs): + def export_private_key(self, name = None, **kwargs): + """ + Export the private key of the specified key pair. + + :param name: SSH key pair name. + :type name: str + """ try: request = ExportPrivateKeyRequest() - keypairbody = KeypairBean( - name=name - ) - request.body = ExportPrivateKeyRequestBody( - keypair=keypairbody - ) + key_pair_body = KeypairBean(name = name) + request.body = ExportPrivateKeyRequestBody(keypair = key_pair_body) response = self.dew_client.kps_client.export_private_key(request) - self.logger.info("Successfully exported private key👇") + self.logger.info("Successfully exported private key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def delete_keypair(self,keypair_name=None,**kwargs): + def delete_keypair(self, keypair_name = None, **kwargs): + """ + Delete SSH key pair. + + Args: + :param keypair_name: Key pair name. + :type keypair_name: str + """ try: - request = DeleteKeypairRequest(keypair_name=keypair_name) + request = DeleteKeypairRequest(keypair_name = keypair_name) response = self.dew_client.kps_client.delete_keypair(request) self.logger.info("Successfully deleted keypair") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def associate_keypair(self, keypair_name = None,type = None, key = None,id = None, disable_password = False, port = None, **kwargs): + """ + Bind a new SSH key pair to the specified virtual machine (replace or reset, replacement requires providing + the configured SSH key pair private key of the virtual machine; reset does not require providing the SSH key + pair private key of the virtual machine). + + Args: + :param keypair_name: Key pair name. + :type keypair_name: str + + :param id: Virtual machine id that needs to bind (replace or reset) SSH key pairs. + :type id: str - def associate_keypair(self,keypair_name=None,type=None,key=None,id=None, disable_password=False, port=None,**kwargs): + :param type: The value is of enumeration type. password or keypair. + :type type: str + + :param key: - When type is the enumeration value password, key represents the password- When type is the enumeration + value keypair, key represents the private key. + :type key: str + """ try: request = AssociateKeypairRequest() - authServer = Auth( - type=type, - key=key - ) - serverbody = EcsServerInfo( - id=id, - auth=authServer, - disable_password=disable_password, - port=port + auth_server = Auth(type = type, key = key) + server_body = EcsServerInfo( + id = id, + auth = auth_server, + disable_password = disable_password, + port = port ) request.body = AssociateKeypairRequestBody( - server=serverbody, - keypair_name=keypair_name + server = server_body, + keypair_name = keypair_name ) response = self.dew_client.kps_client.associate_keypair(request) - self.logger.info("Successfully associate_keypair👇") + self.logger.info("Successfully associate_keypair:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.info(id) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def batch_associate_keypair(self,keypair_name=[],type=[],key=[],id=[],disable_password=[],port=[],**kwargs): + def batch_associate_keypair(self, keypair_name = None, type = None, key = None, id = None, disable_password = None, port = None, **kwargs): + """ + Batch bind new SSH key pairs to the specified virtual machine. + + Args: + :param keypair_name: The name of the SSH key pair + :type keypair_name: list[str] + + :param id: List of virtual machine IDs that require binding (replacing or resetting) SSH key pairs. + :type id: list[str] + """ try: request = BatchAssociateKeypairRequest() - listBatchKeypairsbody = [] - for s in range(len(keypair_name),**kwargs): - authServer = Auth( - type=type[s], - key=key[s] + list_batch_keypairs_body = [] + if isinstance(keypair_name,list): + for s in range(len(keypair_name)): + auth_server = Auth( + type = type[s] if type is not None else None, + key = key[s] if key is not None else None + ) + server_satch_keypairs = EcsServerInfo( + id = id[s] if id is not None else None, + auth = auth_server, + disable_password = disable_password[s] if disable_password is not None else None, + port = port[s] if port is not None else None + ) + list_batch_keypairs_body.append(AssociateKeypairRequestBody( + keypair_name = keypair_name[s] if keypair_name is not None else None, + server = server_satch_keypairs + )) + else: + auth_server = Auth( + type = type, + key = key + ) + server_satch_keypairs = EcsServerInfo( + id = id, + auth = auth_server, + disable_password = disable_password, + port = port ) - serverBatchKeypairs = EcsServerInfo( - id=id[s], - auth=authServer, - disable_password=disable_password[s], - port=port[s] - ) - listBatchKeypairsbody.append(AssociateKeypairRequestBody( - keypair_name=keypair_name[s], - server=serverBatchKeypairs + list_batch_keypairs_body.append(AssociateKeypairRequestBody( + keypair_name = keypair_name, + server = server_satch_keypairs )) - + request.body = BatchAssociateKeypairRequestBody( - batch_keypairs=listBatchKeypairsbody + batch_keypairs = list_batch_keypairs_body ) response = self.dew_client.kps_client.batch_associate_keypair(request) - self.logger.info("Successfully batch_associate_keypair👇") + self.logger.info("Successfully batch_associate_keypair:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def delete_all_failed_task(self,**kwargs): + def delete_all_failed_task(self, **kwargs): + """ + Delete task information that failed the operation. + """ try: request = DeleteAllFailedTaskRequest() response = self.dew_client.kps_client.delete_all_failed_task(request) - self.logger.info("Successfully delete_all_failed_task👇") + self.logger.info("Successfully delete_all_failed_task:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def delete_failed_task(self,task_id,**kwargs): + def delete_failed_task(self, task_id, **kwargs): + """ + Delete failed tasks. + + :param task_id: Task ID + :type task_id: str + """ try: request = DeleteFailedTaskRequest( - task_id=task_id, + task_id = task_id, ) response = self.dew_client.kps_client.delete_failed_task(request) - self.logger.info("Successfully delete_failed_task👇") + self.logger.info("Successfully delete_failed_task:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def disassociate_keypair(self,id=None,type=None,key=None,**kwargs): + def disassociate_keypair(self, id = None, type = None, key = None, **kwargs): + """ + Unbind SSH key pairs to the specified virtual machine and restore SSH password login. + :param id: Virtual machine ID that needs to bind (replace or reset) SSH key pairs + :type id: str + """ try: request = DisassociateKeypairRequest() - authServer = Auth( - type=type, - key=key - ) - serverbody = DisassociateEcsServerInfo( - id=id, - auth=authServer - ) - request.body = DisassociateKeypairRequestBody( - server=serverbody - ) + auth_server = Auth(type = type, key = key) + server_body = DisassociateEcsServerInfo(id = id, auth = auth_server) + request.body = DisassociateKeypairRequestBody(server = server_body) response = self.dew_client.kps_client.disassociate_keypair(request) - self.logger.info("Successfully disassociate_keypair👇") + self.logger.info("Successfully disassociate_keypair:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_failed_task(self,limit=None, offset=None,**kwargs): + def list_failed_task(self, limit = None, offset = None, **kwargs): + """ + Query task information for failed binding, unbinding, and other operations. + """ try: request = ListFailedTaskRequest() request.limit = limit request.offset = offset response = self.dew_client.kps_client.list_failed_task(request) - self.logger.info("Successfully list_failed_task👇") + self.logger.info("Successfully list_failed_task:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_keypair_task(self,task_id=None,**kwargs): + def list_keypair_task(self, task_id = None, **kwargs): + """ + The task returned by the interface based on the SSH key_ ID, query the execution status of the SSH key for the current task. + + Args: + :param task_id: task ID + :type task_id: str + """ try: - request = ListKeypairTaskRequest( - task_id=task_id - ) + request = ListKeypairTaskRequest(task_id = task_id) response = self.dew_client.kps_client.list_keypair_task(request) - self.logger.info("Successfully list_keypair_task👇") + self.logger.info("Successfully list_keypair_task:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_running_task(self,limit=None,offset=None,**kwargs): + def list_running_task(self, limit = None, offset = None, **kwargs): + """ + Query the task information being processed. + """ try: request = ListRunningTaskRequest() request.limit = limit request.offset = offset response = self.dew_client.kps_client.list_running_task(request) - self.logger.info("Successfully list_running_task👇") - + self.logger.info("Successfully list_running_task:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_secret(self,name=None, kms_key_id=None, description=None, - secret_binary=None, secret_string=None, secret_type=None, - auto_rotation=None, rotation_period=None, rotation_config=None, - event_subscriptions=None, enterprise_project_id=None,**kwargs): + def create_secret(self, name = None, kms_key_id = None, description = None, + secret_binary = None, secret_string = None, secret_type = None, + auto_rotation = None, rotation_period = None, rotation_config = None, + event_subscriptions = None, enterprise_project_id = None, **kwargs): + """ + Create a new credential and store the credential value in the initial version of the credential. + The credential management service encrypts the credential values and stores them in the version under the credential object. + Each version can be associated with multiple credential version states, which are used to identify the stage in which the credential + version is in. A version without a version state marker is considered deprecated and can be automatically deleted using the credential + management service. + The initial version status is marked as SYSCURRENT. + + Args: + :param name: The name of the credential to be created. Constraint: The value range is 1 to 64 characters, satisfying the regular matching + "^[a-zA-Z0-9_-]{1,64}$". + :type name: str + """ try: request = CreateSecretRequest() request.body = CreateSecretRequestBody( - secret_string=secret_string, - kms_key_id=kms_key_id, - name=name, - description=description, - secret_binary=secret_binary, - secret_type=secret_type, - auto_rotation=auto_rotation, - rotation_period=rotation_period, - rotation_config=rotation_config, - event_subscriptions=event_subscriptions, - enterprise_project_id=enterprise_project_id + secret_string = secret_string, + kms_key_id = kms_key_id, + name = name, + description = description, + secret_binary = secret_binary, + secret_type = secret_type, + auto_rotation = auto_rotation, + rotation_period = rotation_period, + rotation_config = rotation_config, + event_subscriptions = event_subscriptions, + enterprise_project_id = enterprise_project_id ) response = self.dew_client.cms_client.create_secret(request) - self.logger.info("Successfully create_secret👇") + self.logger.info("Successfully create_secret:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def download_secret_blob(self,secret_name:None,**kwargs): + def download_secret_blob(self, secret_name = None, **kwargs): + """ + Download backup files for specified credentials. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: - request = DownloadSecretBlobRequest( - secret_name=secret_name - ) + request = DownloadSecretBlobRequest(secret_name = secret_name) response = self.dew_client.cms_client.download_secret_blob(request) - self.logger.info("Successfully download_secret_blob👇") + self.logger.info("Successfully download_secret_blob:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_secrets(self,limit=None,marker=None,event_name=None,**kwargs): + def list_secrets(self, limit = None, marker = None, event_name = None, **kwargs): + """ + Query all credentials created by the current user under this project. + """ try: request = ListSecretsRequest() request.limit = limit request.marker = marker request.event_name = event_name response = self.dew_client.cms_client.list_secrets(request) - self.logger.info("Successfully list_secrets👇") + self.logger.info("Successfully list_secrets:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_secret(self,secret_name,**kwargs): + def show_secret(self, secret_name, **kwargs): + """ + Query information for specified credentials. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: - request = ShowSecretRequest( - secret_name=secret_name - ) + request = ShowSecretRequest(secret_name = secret_name) response = self.dew_client.cms_client.show_secret(request) - self.logger.info("Successfully show_secret👇") - + self.logger.info("Successfully show_secret:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def update_secret(self,kms_key_id=None,secret_name=None, description=None, - auto_rotation=None, rotation_period=None, listEventSubscriptionsbody=None,**kwargs): + def update_secret(self, kms_key_id = None, secret_name = None, description = None, + auto_rotation = None, rotation_period = None, listEventSubscriptionsbody = None, **kwargs): + """ + Update metadata information for specified credentials. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: request = UpdateSecretRequest() request.body = UpdateSecretRequestBody( - event_subscriptions=listEventSubscriptionsbody, - description=description, - kms_key_id=kms_key_id, - auto_rotation=auto_rotation, - rotation_period=rotation_period, + event_subscriptions = listEventSubscriptionsbody, + description = description, + kms_key_id = kms_key_id, + auto_rotation = auto_rotation, + rotation_period = rotation_period, ) - request.secret_name=secret_name + request.secret_name = secret_name response = self.dew_client.cms_client.update_secret(request) - self.logger.info("Successfully update_secret👇") + self.logger.info("Successfully update_secret:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_secret_event(self,target_type=None, target_id=None, - target_name=None,name=None, state=None, - listEventTypesbody=[],**kwargs): + def create_secret_event(self, target_type = None, target_id = None, + target_name = None, name = None, state = None, + event_types = None, **kwargs): + """ + Create an event that can be configured on one or more credential objects. When an event is enabled and the + underlying event type is triggered on the credential object, the cloud service will send the corresponding + event notification to the notification subject specified by the event. + + Args: + :param name: The name of the newly created event notification. Constraint: The value range is 1 to 64 + characters, satisfying the regular matching "^ [a-zA-Z0-9_ -] {1,64} $". + :type name: str + + :param event_types:he basic event list for this event notification, with the following basic event types. + SECRET_ VERSION_ CREATED: Version Creation SECRET_ VERSION_ EXPIRED: Version expired SECRET_ ROTATED: credential + rotation SECRET_ DELETED: The credential deletion list cannot contain duplicate underlying event types. + :type event_types: list[str] + + :param state: controls whether an event takes effect. Only the enabled state can trigger the underlying event types + included.ENABLED: enable DisaBLED: disable + :type state: str + + :param target_ Type: The object type of the event notification. + :type target_ Type: str + + :param target_ ID: The object ID of the event notification. + :type target_ Id: str + + :param target_ Name: The name of the object notified by the event. + :type target_ Name: str + """ try: request = CreateSecretEventRequest() - notificationbody = Notification( - target_type=target_type, - target_id=target_id, - target_name=target_name + notification_body = Notification( + target_type = target_type, + target_id = target_id, + target_name = target_name ) request.body = CreateSecretEventRequestBody( - notification=notificationbody, - state=state, - event_types=listEventTypesbody, - name=name, + notification = notification_body, + state = state, + event_types = event_types, + name = name, ) response = self.dew_client.cms_client.create_secret_event(request) - self.logger.info("Successfully create_secret_event👇") + self.logger.info("Successfully create_secret_event:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def upload_secret_blob(self,secret_blob,**kwargs): + def upload_secret_blob(self, secret_blob=None, **kwargs): + """ + Restore credential objects by uploading credential backup files. + + Args: + :param secret_blob: The credential backup file obtained by backing up the specified credential object contains + all current credential version information. The backup file is encrypted and encoded, and its content cannot be read directly. + :type secret_blob: str + """ try: request = UploadSecretBlobRequest() - request.body = UploadSecretBlobRequestBody( - secret_blob=secret_blob - ) + request.body = UploadSecretBlobRequestBody(secret_blob = secret_blob) response = self.dew_client.cms_client.upload_secret_blob(request) - self.logger.info("Successfully upload_secret_blob👇") + self.logger.info("Successfully upload_secret_blob:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: self.logger.error(e.status_code) self.logger.error(e.request_id) self.logger.error(e.error_code) - def rotate_secret(self,secret_name=None,**kwargs): + def rotate_secret(self,secret_name = None, **kwargs): + """ + Immediately execute the rotation of credentials. Create a new credential version within the specified credentials to encrypt + and store randomly generated credential values in the background. At the same time, mark the newly created credential version + as SYSCURRENT status. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: - request = RotateSecretRequest( - secret_name=secret_name - ) + request = RotateSecretRequest(secret_name = secret_name) response = self.dew_client.cms_client.rotate_secret(request) - self.logger.info("Successfully rotate_secret👇") + self.logger.info("Successfully rotate_secret:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def restore_secret(self,secret_name,**kwargs): + def restore_secret(self,secret_name, **kwargs): + """ + Cancel the scheduled deletion task of credentials and restore the usable state of the credential object. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: - request = RestoreSecretRequest(secret_name=secret_name) + request = RestoreSecretRequest(secret_name = secret_name) response = self.dew_client.cms_client.restore_secret(request) - self.logger.info("Successfully restore_secret👇") + self.logger.info("Successfully restore_secret:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def delete_secret_for_schedule(self,recovery_window_in_days=None,secret_name=None,**kwargs): + def delete_secret_for_schedule(self,recovery_window_in_days = None,secret_name = None, **kwargs): + """ + Specify a delayed deletion time, create a scheduled task to delete credentials, and set a delayed deletion time of 7-30 days. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + + :param recovery_ Window_ In_ Days: Create a task to delete credentials on a scheduled basis, and specify the number of days + that can be recovered. Constraints: 7-30. Default value: 30. + :type recovery_ Window_ In_ Days: int + """ try: - request = DeleteSecretForScheduleRequest(secret_name=secret_name) + request = DeleteSecretForScheduleRequest(secret_name = secret_name) request.body = DeleteSecretForScheduleRequestBody( - recovery_window_in_days=recovery_window_in_days + recovery_window_in_days = recovery_window_in_days ) response = self.dew_client.cms_client.delete_secret_for_schedule(request) - self.logger.info("Successfully delete_secret_for_schedule👇") - + self.logger.info("Successfully delete_secret_for_schedule:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def delete_secret(self,secret_name,**kwargs): + def delete_secret(self,secret_name, **kwargs): + """ + Immediately delete the specified credentials and cannot recover them. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: - request = DeleteSecretRequest(secret_name=secret_name) + request = DeleteSecretRequest(secret_name = secret_name) response = self.dew_client.cms_client.delete_secret(request) - self.logger.info("Successfully delete_secret👇") + self.logger.info("Successfully delete_secret:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_secret_version(self,secret_name=None,secret_binary=None, - secret_string=None, version_stages=None, expire_time=None,**kwargs): + def create_secret_version(self,secret_name = None,secret_binary = None, + secret_string = None, version_stages = None, expire_time = None, **kwargs): + """ + Create a new credential version within the specified credentials to encrypt and store the new credential values. + By default, newly created credential versions are marked as SYSCURRENT, while the previous credential version marked + with SYSCURRENT is marked as SYSPREVIOUS. You can override the default behavior by specifying the Version Stage parameter. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: request = CreateSecretVersionRequest(secret_name=secret_name) request.body = CreateSecretVersionRequestBody( - secret_string=secret_string, - secret_binary=secret_binary, - version_stages=version_stages, - expire_time=expire_time + secret_string = secret_string, + secret_binary = secret_binary, + version_stages = version_stages, + expire_time = expire_time ) response = self.dew_client.cms_client.create_secret_version(request) - self.logger.info("Successfully create_secret_version👇") + self.logger.info("Successfully create_secret_version:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_secret_versions(self,secret_name=None, marker=None, limit=None,**kwargs): + def list_secret_versions(self,secret_name = None, marker = None, limit = None, **kwargs): + """ + Query version list information under specified credentials. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: request = ListSecretVersionsRequest() request.secret_name = secret_name request.marker = marker request.limit = limit response = self.dew_client.cms_client.list_secret_versions(request) - self.logger.info("Successfully list_secret_versions👇") + self.logger.info("Successfully list_secret_versions:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_secret_version(self,secret_name=None,version_id=None,**kwargs): + def show_secret_version(self,secret_name = None,version_id = None, **kwargs): + """ + Query the information of the specified credential version and the plaintext credential value in the version, + only the credentials with ENABLED status can be queried. The latest version of the credentials can be accessed + through/v1/{project_id}/secrets/{secretname}/versions/latest (i.e. assigning {version _id} in the current interface URL as latest) + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + + :param version_id: The version identifier of the credential. + :type version_id: str + """ try: request = ShowSecretVersionRequest() - request.secret_name=secret_name + request.secret_name = secret_name request.version_id = version_id response = self.dew_client.cms_client.show_secret_version(request) - self.logger.info("Successfully show_secret_version👇") + self.logger.info("Successfully show_secret_version:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def update_version(self,secret_name=None, version_id=None, expire_time=None,**kwargs): + def update_version(self,secret_name = None, version_id = None, expire_time = None, **kwargs): + """ + Currently, it supports updating the validity period of specified credential versions, and can only update + credentials with ENABLED status. When the event associated with the subscription includes a basic event type + of "version expiration", only one event notification will be triggered after each version expiration update. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + + :param version_id: The version identifier of the credential. + :type version_id: str + + :param expire_time: The expiration time of the credential version, timestamp, is the total number of seconds + from January 1, 1970 to that time. The default is empty, and the value used to determine the validity period + when subscribing to the "version expiration" event type for credentials. + :type expire_time: int + """ try: request = UpdateVersionRequest() - request.version_id=version_id - request.secret_name=secret_name + request.version_id = version_id + request.secret_name = secret_name request.body = UpdateVersionRequestBody( - expire_time=expire_time + expire_time = expire_time ) response = self.dew_client.cms_client.update_version(request) - self.logger.info("Successfully update_version👇") + self.logger.info("Successfully update_version:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def show_secret_stage(self, secret_name=None, stage_name=None, **kwargs): + """ + Query the version information of the specified credential version status marker. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + + :param stage_name: The name of the credential version status. + :type stage_name: str + """ + try: + request = ShowSecretStageRequest(secret_name=secret_name,stage_name=stage_name) + response = self.dew_client.cms_client.show_secret_stage(request) + self.logger.info("Successfully show_secret_stage:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def update_secret_stage(self, secret_name = None, stage_name = None, version_id = None, **kwargs): + """ + Update the version status of credentials. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + + :param stage_name: The name of the credential version status.matching '^[a-zA-Z0-9_-]{1,64}$' + :type stage_name: str + """ + try: + request = UpdateSecretStageRequest(secret_name = secret_name, stage_name = stage_name) + request.body = UpdateSecretStageRequestBody(version_id = version_id) + response = self.dew_client.cms_client.update_secret_stage(request) + self.logger.info("Successfully update_secret_stage:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def delete_secret_stage(self, secret_name = None, stage_name = None, **kwargs): + """ + Delete the version status of credentials. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + + :param stage_name: The name of the credential version status. + :type stage_name: str + """ + try: + request = DeleteSecretStageRequest(secret_name = secret_name, stage_name = stage_name) + response = self.dew_client.cms_client.delete_secret_stage(request) + self.logger.info("Successfully delete_secret_stage:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def batch_create_or_delete_tags(self, secret_id = None, key = None, value = None, action = None, sequence = None, **kwargs): + """ + Batch add or remove credential labels. + + Args: + :param secret_id: Credential ID + :type secret_id: str + + :param key: The name of the tag. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + The value range is from 1 to 128 characters, which satisfies regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L} + \\\\p{Z}\\\\p{N}_.:=+\\\\-@]*)(?<!\\\\s)$\" + :type key: list[str] + + :param action: Operation identifier: limited to "create" and "delete" only. + :type action: str + """ + try: + request = BatchCreateOrDeleteTagsRequest(secret_id = secret_id) + + + listTagsbody = [] + if isinstance(key,list): + for s in range(len(key)): + listTagsbody.append(TagItem(key =key[s], + value = value[s] if value is not None else None)) + else: + listTagsbody.append(TagItem(key =key, value = value)) + + request.body = BatchCreateOrDeleteTagsRequestBody( + action=action, + tags=listTagsbody, + sequence=sequence + ) + response = self.dew_client.cms_client.batch_create_or_delete_tags(request) + self.logger.info("Successfully batch_create_or_delete_tags:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error("status_code= %s",e.status_code) - self.logger.error("request_id= %s",e.request_id) - self.logger.error("error_code= %s",e.error_code) - self.logger.error("error_msg= %s",e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def create_secret_tag(self, secret_id = None, key = None, value = None, **kwargs): + """ + Add credential labels. + + Args: + :param secret_id: Credential ID + :type secret_id: str + + :param key: The name of the tag. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + The value range is from 1 to 128 characters, which satisfies regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L} + \\\\p{Z}\\\\p{N}_.:=+\\\\-@]*)(?<!\\\\s)$\" + :type key: str + """ + try: + request = CreateSecretTagRequest(secret_id = secret_id) + tagbody = TagItem( + key = key, + value = value, + ) + request.body = CreateSecretTagRequestBody( + tag=tagbody + ) + response = self.dew_client.cms_client.create_secret_tag(request) + self.logger.info("Successfully create_secret_tag:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + def delete_secret_tag(self, secret_id = None, key = None, **kwargs): + """ + Delete credential labels. + + Args: + :param secret_id: Credential ID + :type secret_id: str + + :param key: The name of the tag. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + The value range is from 1 to 128 characters, which satisfies regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L} + \\\\p{Z}\\\\p{N}_.:=+\\\\-@]*)(?<!\\\\s)$\" + :type key: str + """ + try: + request = DeleteSecretTagRequest(secret_id = secret_id, key = key) + response = self.dew_client.cms_client.delete_secret_tag(request) + self.logger.info("Successfully delete_secret_tag:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def list_project_secrets_tags(self,**kwargs): + """ + Query the collection of all credential labels for the user under the specified project. + """ + try: + request = ListProjectSecretsTagsRequest() + response = self.dew_client.cms_client.list_project_secrets_tags(request) + self.logger.info("Successfully list_project_secrets_tags:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def list_resource_instances(self,resource_instances = None, values = None, key = None, limit = None, offset=None, action = None, matches = None, sequence = None, **kwargs): + """ + Query credential instances. Filter user credentials through tag filtering and return a list of credentials. + + Args: + :param action: Operation identifier (can be set as "filter" or "count")- Filter: represents filtering + - Count: represents the total number of queries. + :type action: str + + :param resource_instances: Set the value to resource_instances. + :type resource_instances: str + """ + try: + request = ListResourceInstancesRequest(resource_instances = resource_instances) + listTagsbody = [] + if isinstance(key,list): + for s in range(len(key)): + listTagsbody.append(Tag(key = key[s] if key is not None else None, + values = values[s] if values is not None else None)) + else: + listTagsbody.append(Tag(key = key, values = values)) + request.body = ListResourceInstancesRequestBody( + tags = listTagsbody if key is not None else None, + action = action, + matches = matches, + sequence = sequence, + offset = offset, + limit = limit + ) + response = self.dew_client.cms_client.list_resource_instances(request) + self.logger.info("Successfully list_resource_instances:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def list_secret_tags(self, secret_id = None, **kwargs): + """ + Query credential labels. + + Args: + :param secret_id: Credential ID + :type secret_id: str + """ + try: + request = ListSecretTagsRequest(secret_id = secret_id) + response = self.dew_client.cms_client.list_secret_tags(request) + self.logger.info("Successfully list_secret_tags:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def delete_secret_event(self, event_name = None, **kwargs): + """ + Immediately delete the specified event and cannot be restored. If there is a credential reference in the event, + it cannot be deleted. Please dissociate it first. + + Args: + :param event_name: The name of the event notification. + :type event_name: str + """ + try: + request = DeleteSecretEventRequest(event_name = event_name) + response = self.dew_client.cms_client.delete_secret_event(request) + self.logger.info("Successfully delete_secret_event:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + def list_secret_events(self, marker = None, limit = None, **kwargs): + """ + Query all events created by the current user under this project + """ + try: + request = ListSecretEventsRequest() + request.limit =limit + request.marker = marker + response = self.dew_client.cms_client.list_secret_events(request) + self.logger.info("Successfully list_secret_events:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def show_secret_event(self, event_name = None, **kwargs): + """ + Query information for a specified event. + + Args: + :param event_name: The name of the event notification. + :type event_name: str + """ + try: + request = ShowSecretEventRequest(event_name = event_name) + response = self.dew_client.cms_client.show_secret_event(request) + self.logger.info("Successfully show_secret_event:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def update_secret_event(self, event_name = None, state = None, event_types = None, notification = None, **kwargs): + """ + Update metadata information for specified events. The metadata that supports updates includes event enable status, + basic type list, and notification topic. + + Args: + :param event_name: The name of the event notification. + :type event_name: str + """ + try: + request = UpdateSecretEventRequest(event_name = event_name) + request.body = UpdateSecretEventRequestBody( + state = state, + event_types = event_types, + notification = notification + ) + response = self.dew_client.cms_client.update_secret_event(request) + self.logger.info("Successfully update_secret_event:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def list_notification_records(self, marker = None, limit = None, **kwargs): + """ + Query triggered event notification records. + """ + try: + request = ListNotificationRecordsRequest( + limit = limit, + marker = marker + ) + response = self.dew_client.cms_client.list_notification_records(request) + self.logger.info("Successfully list_notification_records:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def batch_create_kms_tags(self, key_id = None, key = None, value = None, action = None, **kwargs): + """ + + Args: + :param key_id: key ID + :type key_id: str + + :param action: Operation identifier: limited to "create" and "delete". + :type action: str + + :param key: The name of the label. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + Value range from 1 to 128 characters, satisfying regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L}\\\\p{Z}\\\\p{N} + _.:=+\\\\-@]*)(?<!\\\\s)$\" + :type key: list[str] + """ + try: + request = BatchCreateKmsTagsRequest(key_id = key_id) + listTagsbody = [] + if isinstance(key,list): + for s in range(len(key)): + listTagsbody.append(TagItem(key =key[s], + value = value[s] if value is not None else None)) + else: + listTagsbody.append(TagItem(key =key, value = value)) + request.body = BatchCreateKmsTagsRequestBody( + action=action, + tags=listTagsbody + ) + response = self.dew_client.kms_client.batch_create_kms_tags(request) + self.logger.info("Successfully batch_create_kms_tags:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def create_kms_tag(self, key_id = None, key = None, value = None, **kwargs): + """ + Add key labels. + + Args: + :param key_id: key ID + :type key_id: str + + :param key: The name of the label. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + Value range from 1 to 128 characters, satisfying regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L}\\\\p{Z}\\\\p{N} + _.:=+\\\\-@]*)(?<!\\\\s)$\" + :type key: str + """ + try: + request = CreateKmsTagRequest(key_id = key_id) + tagbody = TagItem( + key = key, + value = value + ) + request.body = CreateKmsTagRequestBody( + tag=tagbody + ) + response = self.dew_client.kms_client.create_kms_tag(request) + self.logger.info("Successfully create_kms_tag:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def list_kms_tags(self, **kwargs): + """ + Query all label collections of the user under the specified project. + """ + try: + request = ListKmsTagsRequest() + response = self.dew_client.kms_client.list_kms_tags(request) + self.logger.info("Successfully list_kms_tags:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def delete_tag(self, key_id = None, key = None, **kwargs): + """ + Delete key label. + + Args: + :param key_id: Key ID + :type key_id: str + :param key: Value of label key + :type key: str + """ + try: + request = DeleteTagRequest(key_id = key_id, key = key) + response = self.dew_client.kms_client.delete_tag(request) + self.logger.info("Successfully delete_tag:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + def list_kms_by_tags(self,key = None, values = None, limit=None, offset=None, action=None, tags=None, matches=None, sequence=None, **kwargs): + """ + Query key instances. Filter through tags to query detailed information about the specified user's master key. + """ + try: + request = ListKmsByTagsRequest(resource_instances = "resource_instances") + listTagsbody = [] + if isinstance(key,list): + for s in range(len(key)): + listTagsbody.append(Tag(key = key[s] if key is not None else None, + values = values[s] if values is not None else None)) + else: + listTagsbody.append(Tag(key = key, values = values)) + request.body = ListKmsByTagsRequestBody( + tags = listTagsbody if key is not None else None, + action = action, + offset = offset, + limit = limit, + sequence = sequence, + matches = matches + ) + response = self.dew_client.kms_client.list_kms_by_tags(request) + self.logger.info("Successfully list_kms_by_tags:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + def show_kms_tags(self, key_id = None, **kwargs): + """ + Query the key label. + + Args: + :param key_id: Key ID + :type key_id: str + """ + try: + request = ShowKmsTagsRequest(key_id = key_id) + response = self.dew_client.kms_client.show_kms_tags(request) + self.logger.info("Successfully show_kms_tags:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + + def create_key_store(self, keystore_alias = None, hsm_cluster_id = None, hsm_ca_cert = None, **kwargs): + """" + Create a tenant exclusive key repository that uses DHSM instances as key storage. + + Args: + :param keystore_alias: Exclusive key repository alias, with a value range of 1 to 255 characters, satisfies regular matching + "^[a-zA-Z0-9:/_-]{1,255}$", and does not have the same name as existing exclusive key repository aliases. + :type keystore_alias: str + :param hsm_cluster_id: The DHSM cluster ID requires that the cluster has not yet created a dedicated key repository. + :type hsm_cluster_id: str + :param hsm_ca_cert: CA certificate for DHSM cluster + :type hsm_ca_cert: str + """ + try: + request = CreateKeyStoreRequest() + request.body = CreateKeyStoreRequestBody( + hsm_ca_cert = hsm_ca_cert, + hsm_cluster_id = hsm_cluster_id, + keystore_alias = keystore_alias + ) + response = self.dew_client.kms_client.create_key_store(request) + self.logger.info("Successfully create_key_store:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") \ No newline at end of file diff --git a/prefect_huaweicloud/dew_client.py b/prefect_huaweicloud/dew_client.py index 7aa3751..28feb9b 100644 --- a/prefect_huaweicloud/dew_client.py +++ b/prefect_huaweicloud/dew_client.py @@ -8,21 +8,21 @@ from huaweicloudsdkcsms.v1 import CsmsClient class DewClient(): - def __init__(self,region_id=None, ak=None, sk=None, *args, **kwargs): + def __init__(self,region_id = None, ak = None, sk = None, *args, **kwargs): if not ak or not sk: raise Exception("please input both huawei_cloud_access_key_id and huawei_cloud_secret_access_key") - self.region_id=region_id - self.__ak=ak - self.__sk=sk - self.kms_client=KmsClient.new_builder() \ + self.region_id = region_id + self.__ak = ak + self.__sk = sk + self.kms_client = KmsClient.new_builder() \ .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ .with_region(KmsRegion.value_of(self.region_id)) \ .build() - self.kps_client=KpsClient.new_builder() \ + self.kps_client = KpsClient.new_builder() \ .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ .with_region(KpsRegion.value_of(self.region_id)) \ .build() - self.cms_client=CsmsClient.new_builder() \ + self.cms_client = CsmsClient.new_builder() \ .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ .with_region(CsmsRegion.value_of(self.region_id)) \ .build() diff --git a/prefect_huaweicloud/test/test_dew_block.py b/prefect_huaweicloud/test/test_dew_block.py index 7cf6a7c..d890310 100644 --- a/prefect_huaweicloud/test/test_dew_block.py +++ b/prefect_huaweicloud/test/test_dew_block.py @@ -5,57 +5,108 @@ from dew_block import DewBlock from prefect import flow,task -def kms_params(huaweicloud_dew_block, key_alias=None): - test_key=huaweicloud_dew_block.create_key(key_alias=key_alias) +def kms_params(huaweicloud_dew_block, key_alias = None,key_spec = None): + test_key = huaweicloud_dew_block.create_key(key_alias = key_alias) return dict( - key_alias=key_alias, - key_id=test_key.key_info.key_id, - key_description=None, - pending_days=7, - random_data_length=512, - datakey_length=512, - datakey_plain_length=64, - datakey_cipher_length=64, - cipher_text=None, - plain_text=None, - datakey_dgst=None, - - grantee_principal="0f9eaeef3b7347f3804c2b27d126273e", + key_alias = key_alias, + key_id = test_key.key_info.key_id, + key_description = None, + pending_days = 7, + random_data_length = 512, + datakey_length = 512, + datakey_plain_length = 64, + datakey_cipher_length = 64, + cipher_text = None, + plain_text = None, + datakey_dgst = None, + + grantee_principal = "0f9eaeef3b7347f3804c2b27d126273e", listOperationsbody = [ "describe-key", "create-datakey", "encrypt-datakey"], - grant_id=None, - encryption_algorithm="SYMMETRIC_DEFAULT", - rotation_interval=30, + grant_id = None, + encryption_algorithm = "SYMMETRIC_DEFAULT", + rotation_interval = 30, + + signing_algorithm = "RSASSA_PKCS1_V1_5_SHA_256", + message = "09d158717e34db02afbe64c1d96b7a7cb3e846fb04f642b6257caccf1ca06485", + message_type = "RAW", + signature = None, + recovery_window_in_days = 7, + action = "create", + key = "key0", + version_id = "v1.0", + keystore_alias="keystore_alias_01", + + + ) def kps_params(huaweicloud_dew_block, name): - key_pair_list=huaweicloud_dew_block.list_keypairs() + key_pair_list = huaweicloud_dew_block.list_keypairs() if name in list(x.keypair.name for x in key_pair_list.keypairs[:]): - huaweicloud_dew_block.delete_keypair(keypair_name=name) - test_key=huaweicloud_dew_block.create_keypair(name=name) + huaweicloud_dew_block.delete_keypair(keypair_name = name) + test_key = huaweicloud_dew_block.create_keypair(name = name) return dict( - name=name, - keypair_name=name, - private_key=test_key.keypair.private_key, - # key_id=test_key.keypair.user_id, - description=None + name = name, + keypair_name = name, + private_key = test_key.keypair.private_key, + description = None, + id = "59d5bfcf-20c9-427f-9ea6-a4f02504a9ea", + type = "password", + key = "Lky523175094", + task_id = None, + disable_password = False, ) +def csms_params(huaweicloud_dew_block, name,secret_string, secret_type,event_name): + secret_list = huaweicloud_dew_block.list_secrets() + if name in list(x.name for x in secret_list.secrets[:]): + huaweicloud_dew_block.delete_secret(secret_name = name) + test_secret = huaweicloud_dew_block.create_secret(name,secret_string = secret_string,secret_type = secret_type) + + secret_event = huaweicloud_dew_block.list_secret_events() + + if event_name in list(x.name for x in secret_event.events[:]): + huaweicloud_dew_block.delete_secret_event(event_name = event_name) + return dict( + secret_name = test_secret.secret.name, + version_id = "v2", + secret_blob = None, + expire_time = None, + secret_string = secret_string, + stage_name = "SYSCURRENT", + secret_id = test_secret.secret.id, + key = "tag2024", + action = "create", + value = "tag2024", + values = "tag2024", + resource_instances = "resource_instances", + name = "demo_event", + event_types = ["SECRET_VERSION_CREATED"], + state = "ENABLED", + target_type = "SMN", + target_id = "urn:smn:cn-south-1:SecertExpirationTest", + target_name = "SecertExpirationNotificationTest", + + + event_name = "demo_event" + ) + @flow def test_key_lifecycle_management(kms_params, huaweicloud_dew_block): - row_key_alias=kms_params['key_alias'] + row_key_alias = kms_params['key_alias'] huaweicloud_dew_block.create_key(**kms_params) huaweicloud_dew_block.disable_key(**kms_params) huaweicloud_dew_block.enable_key(**kms_params) - kms_params['key_alias']="test_alias" + kms_params['key_alias'] = "test_alias" huaweicloud_dew_block.update_key_Alias(**kms_params) - kms_params['key_alias']=row_key_alias + kms_params['key_alias'] = row_key_alias huaweicloud_dew_block.update_key_Alias(**kms_params) - kms_params['key_description']="test_update_description" + kms_params['key_description'] = "test_update_description" huaweicloud_dew_block.update_key_description(**kms_params) huaweicloud_dew_block.delete_key(**kms_params) huaweicloud_dew_block.cancel_key_deletion(**kms_params) @@ -65,43 +116,54 @@ def test_key_lifecycle_management(kms_params, huaweicloud_dew_block): @flow def test_data_key_management(kms_params, huaweicloud_dew_block): huaweicloud_dew_block.create_data_key_without_plaintext(**kms_params) - create_data_key_response=huaweicloud_dew_block.create_data_key(**kms_params) + create_data_key_response = huaweicloud_dew_block.create_data_key(**kms_params) huaweicloud_dew_block.create_random(**kms_params) - kms_params["cipher_text"]=create_data_key_response.cipher_text - decrypt_data_key_response=huaweicloud_dew_block.decrypt_data_key(**kms_params) - kms_params["datakey_dgst"]=decrypt_data_key_response.datakey_dgst - kms_params["plain_text"]=decrypt_data_key_response.data_key+decrypt_data_key_response.datakey_dgst + kms_params["cipher_text"] = create_data_key_response.cipher_text + decrypt_data_key_response = huaweicloud_dew_block.decrypt_data_key(**kms_params) + kms_params["datakey_dgst"] = decrypt_data_key_response.datakey_dgst + kms_params["plain_text"] = decrypt_data_key_response.data_key+decrypt_data_key_response.datakey_dgst huaweicloud_dew_block.encrypt_data_key(**kms_params) @flow def test_key_grant_management(kms_params, huaweicloud_dew_block): - create_grant_response=huaweicloud_dew_block.create_grant(**kms_params) - kms_params["grant_id"]=create_grant_response.grant_id + create_grant_response = huaweicloud_dew_block.create_grant(**kms_params) + kms_params["grant_id"] = create_grant_response.grant_id huaweicloud_dew_block.list_retirable_grants(**kms_params) - # huaweicloud_dew_block.cancel_self_grant(**kms_params) + huaweicloud_dew_block.cancel_self_grant(**kms_params) huaweicloud_dew_block.cancel_grant(**kms_params) huaweicloud_dew_block.list_grants(**kms_params) @flow def test_key_pair_management(kps_params, huaweicloud_dew_block): - row_keypair_name=kps_params['name'] + row_keypair_name = kps_params['name'] huaweicloud_dew_block.import_private_key(**kps_params) huaweicloud_dew_block.export_private_key(**kps_params) huaweicloud_dew_block.list_keypair_detail(**kps_params) + huaweicloud_dew_block.list_keypairs(**kps_params) huaweicloud_dew_block.clear_private_key(**kps_params) - kps_params['description']="test_update_description" + kps_params['description'] = "test_update_description" huaweicloud_dew_block.update_keypair_description(**kps_params) huaweicloud_dew_block.delete_keypair(**kps_params) +@flow +def test_key_pair_task_management(kps_params, huaweicloud_dew_block): + kps_params["task_id"] = huaweicloud_dew_block.associate_keypair(**kps_params).task_id + huaweicloud_dew_block.batch_associate_keypair(**kps_params) + huaweicloud_dew_block.delete_all_failed_task(**kps_params) + huaweicloud_dew_block.delete_failed_task(**kps_params) + huaweicloud_dew_block.disassociate_keypair(**kps_params) + huaweicloud_dew_block.list_failed_task(**kps_params) + huaweicloud_dew_block.list_keypair_task(**kps_params) + huaweicloud_dew_block.list_running_task(**kps_params) @flow def test_small_data_encryption(kms_params, huaweicloud_dew_block): - encrypt_data_response=huaweicloud_dew_block.encrypt_data(**kms_params) - kms_params["cipher_text"]=encrypt_data_response.cipher_text + encrypt_data_response = huaweicloud_dew_block.encrypt_data(**kms_params) + kms_params["cipher_text"] = encrypt_data_response.cipher_text huaweicloud_dew_block.decrypt_data(**kms_params) @@ -110,26 +172,111 @@ def test_small_data_encryption(kms_params, huaweicloud_dew_block): def test_list_key(kms_params, huaweicloud_dew_block): huaweicloud_dew_block.list_keys(**kms_params) huaweicloud_dew_block.list_key_detail(**kms_params) - huaweicloud_dew_block.show_public_key(key_id="029c2ea1-196d-47a4-b377-ac8bb359b344") + huaweicloud_dew_block.show_public_key(key_id = "95afc13e-a5ed-4271-b8e9-a71079e8c6b3") huaweicloud_dew_block.show_user_instances(**kms_params) huaweicloud_dew_block.show_user_quotas(**kms_params) @flow -def key_rotation_management(kms_params, huaweicloud_dew_block): +def test_key_rotation_management(kms_params, huaweicloud_dew_block): huaweicloud_dew_block.enable_key_rotation(**kms_params) huaweicloud_dew_block.show_key_rotation_status(**kms_params) huaweicloud_dew_block.update_key_rotation_interval(**kms_params) huaweicloud_dew_block.disable_key_rotation(**kms_params) - -if __name__=="__main__": + + +@flow +def test_signature_verification(kms_params, huaweicloud_dew_block): + kms_params["key_id"] = "95afc13e-a5ed-4271-b8e9-a71079e8c6b3" + row_sign = huaweicloud_dew_block.sign(**kms_params) + kms_params['signature'] = row_sign.signature + huaweicloud_dew_block.validate_signature(**kms_params) + + +@flow +def test_lifecycle_management(csms_params, huaweicloud_dew_block): + huaweicloud_dew_block.show_secret(**csms_params) + csms_params["secret_blob"] = huaweicloud_dew_block.download_secret_blob(**csms_params).secret_blob + huaweicloud_dew_block.update_secret(**csms_params) + huaweicloud_dew_block.delete_secret_for_schedule(**csms_params) + huaweicloud_dew_block.restore_secret(**csms_params) + huaweicloud_dew_block.delete_secret(**csms_params) + huaweicloud_dew_block.upload_secret_blob(**csms_params) + + +@flow +def test_credential_version_management(csms_params, huaweicloud_dew_block): + huaweicloud_dew_block.create_secret_version(**csms_params) + huaweicloud_dew_block.show_secret_version(**csms_params) + huaweicloud_dew_block.list_secret_versions(**csms_params) + csms_params["expire_time"] = 1705868739000 + huaweicloud_dew_block.update_version(**csms_params) + + +@flow +def test_credential_version_status_management(csms_params, huaweicloud_dew_block): + huaweicloud_dew_block.show_secret_stage(**csms_params) + csms_params["version_id"] = "v1" + huaweicloud_dew_block.update_secret_stage(**csms_params) + csms_params["stage_name"] = "ACTIVE" + huaweicloud_dew_block.delete_secret_stage(**csms_params) + + +@flow +def test_voucher_label_management(csms_params, huaweicloud_dew_block): + huaweicloud_dew_block.batch_create_or_delete_tags(**csms_params) + huaweicloud_dew_block.create_secret_tag(**csms_params) + huaweicloud_dew_block.list_project_secrets_tags(**csms_params) + huaweicloud_dew_block.list_resource_instances(resource_instances = "resource_instances", action = "count") + huaweicloud_dew_block.list_secret_tags(**csms_params) + huaweicloud_dew_block.delete_secret_tag(**csms_params) + + +@flow +def test_event_management(csms_params, huaweicloud_dew_block): + huaweicloud_dew_block.create_secret_event(**csms_params) + huaweicloud_dew_block.show_secret_event(**csms_params) + huaweicloud_dew_block.update_secret_event(**csms_params) + huaweicloud_dew_block.delete_secret_event(**csms_params) + huaweicloud_dew_block.list_notification_records(**csms_params) + + +@flow +def test_key_label_management(kms_params, huaweicloud_dew_block): + huaweicloud_dew_block.list_kms_tags(**kms_params) + huaweicloud_dew_block.batch_create_kms_tags(**kms_params) + huaweicloud_dew_block.create_kms_tag(**kms_params) + huaweicloud_dew_block.list_kms_by_tags(action = "count") + huaweicloud_dew_block.show_kms_tags(**kms_params) + huaweicloud_dew_block.delete_tag(**kms_params) + +@flow +def test_query_key_api_version_information(kms_params, huaweicloud_dew_block): + huaweicloud_dew_block.show_versions(**kms_params) + huaweicloud_dew_block.show_version(**kms_params) + + +if __name__ == "__main__": huaweicloud_dew_block = DewBlock.load("test-dew-block") - kms_params=kms_params(huaweicloud_dew_block, key_alias="12-26") - test_key_lifecycle_management(kms_params,huaweicloud_dew_block) - test_key_pair_management(kps_params(huaweicloud_dew_block,name="22-22"),huaweicloud_dew_block) - test_data_key_management(kms_params,huaweicloud_dew_block) - test_key_grant_management(kms_params,huaweicloud_dew_block) - test_small_data_encryption(kms_params,huaweicloud_dew_block) + kms_params = kms_params(huaweicloud_dew_block, key_alias = "1-9") + kps_params = kps_params(huaweicloud_dew_block, name = "22-22") + test_key_lifecycle_management(kms_params, huaweicloud_dew_block) + test_key_pair_management(kps_params, huaweicloud_dew_block) + test_key_pair_task_management(kps_params, huaweicloud_dew_block) + test_data_key_management(kms_params, huaweicloud_dew_block) + test_key_grant_management(kms_params, huaweicloud_dew_block) + test_small_data_encryption(kms_params, huaweicloud_dew_block) test_list_key(kms_params, huaweicloud_dew_block) - key_rotation_management(kms_params, huaweicloud_dew_block) - \ No newline at end of file + test_key_rotation_management(kms_params, huaweicloud_dew_block) + test_signature_verification(kms_params, huaweicloud_dew_block) + csms_params = csms_params(huaweicloud_dew_block, name = "demo", secret_string = "test_secret", secret_type = None, event_name = "demo_event") + test_lifecycle_management(csms_params, huaweicloud_dew_block) + test_credential_version_management(csms_params, huaweicloud_dew_block) + test_credential_version_status_management(csms_params, huaweicloud_dew_block) + test_voucher_label_management(csms_params, huaweicloud_dew_block) + test_event_management(csms_params, huaweicloud_dew_block) + test_key_label_management(kms_params, huaweicloud_dew_block) + test_query_key_api_version_information(kms_params, huaweicloud_dew_block) + + + -- Gitee From 37e85c5dedb41b122a5dc93e7f496371cc384702 Mon Sep 17 00:00:00 2001 From: lky0312 <523175094@qq.com> Date: Fri, 19 Jan 2024 03:05:17 +0800 Subject: [PATCH 04/11] Not important --- .vscode/settings.json | 6 + build/lib/prefect_huaweicloud/__init__.py | 6 + build/lib/prefect_huaweicloud/dew_block.py | 1108 +++++++++++++++++ build/lib/prefect_huaweicloud/dew_client.py | 30 + build/lib/prefect_huaweicloud/obs_block.py | 364 ++++++ .../lib/prefect_huaweicloud/test/__init__.py | 3 + .../test/test_dew_block.py | 153 +++ build/lib/prefect_huaweicloud/test_dew.py | 111 ++ dist/prefect_hwc-0.1.0-py3.11.egg | Bin 0 -> 42312 bytes prefect_huaweicloud/__init__.py | 3 +- .../__pycache__/dew_block.cpython-311.pyc | Bin 0 -> 134130 bytes .../__pycache__/dew_client.cpython-311.pyc | Bin 0 -> 2595 bytes prefect_hwc.egg-info/PKG-INFO | 29 + prefect_hwc.egg-info/SOURCES.txt | 14 + prefect_hwc.egg-info/dependency_links.txt | 1 + prefect_hwc.egg-info/requires.txt | 3 + prefect_hwc.egg-info/top_level.txt | 1 + 17 files changed, 1831 insertions(+), 1 deletion(-) create mode 100644 .vscode/settings.json create mode 100644 build/lib/prefect_huaweicloud/__init__.py create mode 100644 build/lib/prefect_huaweicloud/dew_block.py create mode 100644 build/lib/prefect_huaweicloud/dew_client.py create mode 100644 build/lib/prefect_huaweicloud/obs_block.py create mode 100644 build/lib/prefect_huaweicloud/test/__init__.py create mode 100644 build/lib/prefect_huaweicloud/test/test_dew_block.py create mode 100644 build/lib/prefect_huaweicloud/test_dew.py create mode 100644 dist/prefect_hwc-0.1.0-py3.11.egg create mode 100644 prefect_huaweicloud/__pycache__/dew_block.cpython-311.pyc create mode 100644 prefect_huaweicloud/__pycache__/dew_client.cpython-311.pyc create mode 100644 prefect_hwc.egg-info/PKG-INFO create mode 100644 prefect_hwc.egg-info/SOURCES.txt create mode 100644 prefect_hwc.egg-info/dependency_links.txt create mode 100644 prefect_hwc.egg-info/requires.txt create mode 100644 prefect_hwc.egg-info/top_level.txt diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a4f7a82 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "codecheck.ExcludeDirectory": "", + "codecheck.ScanDirectory": "", + "codecheck.allRule": true, + "codecheck.disabledRules": [] +} \ No newline at end of file diff --git a/build/lib/prefect_huaweicloud/__init__.py b/build/lib/prefect_huaweicloud/__init__.py new file mode 100644 index 0000000..4064758 --- /dev/null +++ b/build/lib/prefect_huaweicloud/__init__.py @@ -0,0 +1,6 @@ +# ensure core blocks are registered + +from prefect_huaweicloud.obs_block import ObsBlock +from prefect_huaweicloud.dew_block import DewBlock + +__all__ = ["ObsBlock","DewBlock"] diff --git a/build/lib/prefect_huaweicloud/dew_block.py b/build/lib/prefect_huaweicloud/dew_block.py new file mode 100644 index 0000000..ff8174f --- /dev/null +++ b/build/lib/prefect_huaweicloud/dew_block.py @@ -0,0 +1,1108 @@ + +from typing import Optional +from logging import Logger +from pydantic import Field, SecretStr +from prefect.blocks.abstract import Block +from prefect.utilities.asyncutils import run_sync_in_worker_thread, sync_compatible +from prefect.logging.loggers import get_logger, get_run_logger +from prefect.exceptions import MissingContextError +from prefect import task +from pydantic import VERSION as PYDANTIC_VERSION +import json +if PYDANTIC_VERSION.startswith("2."): + from pydantic.v1 import Field +else: + from pydantic import Field +from dew_client import DewClient +from huaweicloudsdkkms.v2.model import * +from huaweicloudsdkcore.exceptions import exceptions +from huaweicloudsdkcsms.v1.model import * +from huaweicloudsdkkps.v3.model import * + + +class DewBlock(Block): + + _logo_url = "https://res-static.hc-cdn.cn/cloudbu-site/public/header-icon/Storage/OBS.png" # noqa + _block_type_name = "HuaweiCloud DEW" + _documentation_url = ("https://support.huaweicloud.com/intl/zh-cn/sdk-python-devg-obs/obs_22_0100.html") # noqa + + huawei_cloud_access_key_id: Optional[SecretStr] = Field( + default=None, + description="A specific Huawei Cloud access key ID.", + title="Huawei Cloud Access Key ID:", + ) + huawei_cloud_secret_access_key: Optional[SecretStr] = Field( + default=None, + description="A specific Huawei Cloud secret access key.", + title="Huawei Cloud Access Key Secret:", + ) + huawei_cloud_security_token: Optional[SecretStr] = Field( + default=None, + description="SecurityToken in the temporary access key, " + "You can select a temporary token or AK/SK for authentication", + title="Huawei Cloud Security Token", + ) + region_id:Optional[str] = Field( + default=None, + title="region id", + ) + + def __init__(self,*args, **kwargs): + self.dew_client=DewClient(region_id=kwargs['region_id'], + ak=kwargs['huawei_cloud_access_key_id'], + sk=kwargs['huawei_cloud_secret_access_key']) + + @property + def logger(self) -> Logger: + """ + Returns a logger based on whether the ObjectStorageBlock + is called from within a flow or task run context. + If a run context is present, the logger property returns a run logger. + Else, it returns a default logger labeled with the class's name. + + Returns: + The run logger or a default logger with the class's name. + """ + try: + return get_run_logger() + except MissingContextError: + return get_logger(self.__class__.__name__) + + def create_key(self,key_alias=None, key_spec=None, key_usage=None, key_description=None, + origin=None, enterprise_project_id=None, sequence=None, keystore_id=None, **kwargs): + try: + request = CreateKeyRequest() + request.body = CreateKeyRequestBody( + key_alias=key_alias, + key_spec=key_spec, + key_usage=key_usage, + key_description=key_description, + origin=origin, + enterprise_project_id=enterprise_project_id, + sequence=sequence, + keystore_id=keystore_id + ) + response =self.dew_client.kms_client.create_key(request) + self.logger.debug("Created key") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def delete_key(self,key_id=None,pending_days=None, sequence=None, **kwargs): + try: + request = DeleteKeyRequest() + request.body = ScheduleKeyDeletionRequestBody( + key_id=key_id, + pending_days=pending_days, + sequence=sequence + ) + response = self.dew_client.kms_client.delete_key(request) + self.logger.debug("Successfully delete_key") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def disable_key(self,key_id=None,sequence=None, **kwargs): + try: + request = DisableKeyRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response =self.dew_client.kms_client.disable_key(request) + self.logger.info("Successfully disable_key:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def enable_key(self,key_id=None, sequence=None, **kwargs): + try: + request = EnableKeyRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response =self.dew_client.kms_client.enable_key(request) + self.logger.info("Successfully enable_key:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def update_key_Alias(self,key_id=None, key_alias=None, sequence=None, **kwargs): + try: + request = UpdateKeyAliasRequest() + request.body = UpdateKeyAliasRequestBody( + key_alias=key_alias, + key_id=key_id, + sequence=sequence + ) + response =self.dew_client.kms_client.update_key_alias(request) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def update_key_description(self,key_id=None, key_description=None, sequence=None, **kwargs): + try: + request = UpdateKeyDescriptionRequest() + request.body = UpdateKeyDescriptionRequestBody( + key_id=key_id, + key_description=key_description, + sequence=sequence + ) + response =self.dew_client.kms_client.update_key_description(request) + self.logger.info("Successfully update_key_description:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def cancel_key_deletion(self,key_id=None,sequence=None, **kwargs): + try: + request = CancelKeyDeletionRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.cancel_key_deletion(request) + self.logger.info("Successfully canccel key daletion:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def create_data_key(self,key_id,key_spec=None, datakey_length=None, sequence=None, **kwargs): + try: + request = CreateDatakeyRequest() + request.body = CreateDatakeyRequestBody( + key_id=key_id, + key_spec=key_spec, + datakey_length=datakey_length, + sequence=sequence + ) + response = self.dew_client.kms_client.create_datakey(request) + self.logger.info("Successfully created datakey:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def create_data_key_without_plaintext(self,key_id,key_spec=None, datakey_length=None, sequence=None, **kwargs): + try: + request = CreateDatakeyWithoutPlaintextRequest() + request.body = CreateDatakeyRequestBody( + key_id=key_id, + key_spec=key_spec, + datakey_length=datakey_length, + sequence=sequence + ) + response = self.dew_client.kms_client.create_datakey_without_plaintext(request) + self.logger.info("Successfully created datakey without plaintext:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def create_random(self,random_data_length=None, sequence=None, **kwargs): + try: + request = CreateRandomRequest() + request.body = GenRandomRequestBody( + random_data_length=random_data_length, + sequence=sequence + ) + response = self.dew_client.kms_client.create_random(request) + self.logger.info("Successfully created random:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def decrypt_data_key(self,key_id=None, cipher_text=None, datakey_cipher_length=None, sequence=None, **kwargs): + try: + request = DecryptDatakeyRequest() + request.body = DecryptDatakeyRequestBody( + key_id=key_id, + cipher_text=cipher_text, + datakey_cipher_length=datakey_cipher_length, + sequence=sequence + ) + response = self.dew_client.kms_client.decrypt_datakey(request) + self.logger.info("Successfully decrypted datakey:") + self.logger.info(response) + return response + + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def encrypt_data_key(self,key_id=None, plain_text=None, datakey_plain_length=None, sequence=None, **kwargs): + try: + request = EncryptDatakeyRequest() + request.body = EncryptDatakeyRequestBody( + key_id=key_id, + plain_text=plain_text, + datakey_plain_length=datakey_plain_length, + sequence=sequence + ) + response = self.dew_client.kms_client.encrypt_datakey(request) + self.logger.info("Successfully encrypted datakey:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def create_parameters_for_import(self,key_id,wrapping_algorithm=None, sequence=None, **kwargs): + try: + request = CreateParametersForImportRequest() + request.body = GetParametersForImportRequestBody( + key_id=key_id, + wrapping_algorithm=wrapping_algorithm, + sequence=sequence + ) + response = self.dew_client.kms_client.create_parameters_for_import(request) + self.logger.info("Successfully created parameters for import:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def delete_imported_key_material(self,key_id,sequence=None, **kwargs): + try: + request = DeleteImportedKeyMaterialRequest() + request.body = OperateKeyRequestBody( + key_id = key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.delete_imported_key_material(request) + self.logger.info("Successfully deleted imported key material:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def import_key_material(self,key_id=None, import_token=None, + encrypted_key_material=None, encrypted_privatekey=None, + expiration_time=None, sequence=None, **kwargs): + try: + request = ImportKeyMaterialRequest() + request.body = ImportKeyMaterialRequestBody( + key_id=key_id, + import_token=import_token, + encrypted_key_material=encrypted_key_material, + encrypted_privatekey=encrypted_privatekey, + expiration_time=expiration_time, + sequence=sequence + ) + response = self.dew_client.kms_client.import_key_material(request) + self.logger.info("Successfully imported key material:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def create_grant(self,key_id=None, grantee_principal=None, listOperationsbody=None, + name=None, retiring_principal=None, grantee_principal_type=None, sequence=None, **kwargs): + try: + request = CreateGrantRequest() + request.body = CreateGrantRequestBody( + key_id=key_id, + grantee_principal=grantee_principal, + operations=listOperationsbody, + grantee_principal_type=grantee_principal_type, + retiring_principal=retiring_principal, + name=name, + sequence=sequence + ) + response = self.dew_client.kms_client.create_grant(request) + self.logger.info("Successfully create grant:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(e.status_code) + self.logger.error(e.request_id) + self.logger.error(e.error_code) + self.logger.error(e.error_msg) + + def list_retirable_grants(self,limit=None, marker=None, sequence=None, **kwargs): + try: + request = ListRetirableGrantsRequest() + request.body = ListRetirableGrantsRequestBody( + limit=limit, + marker=marker, + sequence=sequence + ) + response = self.dew_client.kms_client.list_retirable_grants(request) + self.logger.info("Successfully list retirable grants:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(e.status_code) + self.logger.error(e.request_id) + self.logger.error(e.error_code) + self.logger.error(e.error_msg) + + def list_grants(self,key_id=None, limit=None, marker=None, sequence=None, **kwargs): + try: + request = ListGrantsRequest() + request.body = ListGrantsRequestBody( + key_id=key_id, + limit=limit, + marker=marker, + sequence=sequence + ) + response = self.dew_client.kms_client.list_grants(request) + self.logger.info("Successfully list grants:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(e.status_code) + self.logger.error(e.request_id) + self.logger.error(e.error_code) + self.logger.error(e.error_msg) + + def cancel_self_grant(self,key_id=None, grant_id=None, sequence=None, **kwargs): + try: + request = CancelSelfGrantRequest() + request.body = RevokeGrantRequestBody( + grant_id=grant_id, + key_id=key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.cancel_self_grant(request) + self.logger.info("Successfully cancel self grant:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(e.status_code) + self.logger.error(e.request_id) + self.logger.error(e.error_code) + self.logger.error(e.error_msg) + + def cancel_grant(self,key_id=None, grant_id=None, sequence=None, **kwargs): + try: + request = CancelGrantRequest() + request.body = RevokeGrantRequestBody( + grant_id=grant_id, + key_id=key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.cancel_grant(request) + self.logger.info("Successfully cancel grant:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(e.status_code) + self.logger.error(e.request_id) + self.logger.error(e.error_code) + self.logger.error(e.error_msg) + + def decrypt_data(self,cipher_text=None, encryption_algorithm=None, key_id=None, sequence=None, **kwargs): + try: + request = DecryptDataRequest() + request.body = DecryptDataRequestBody( + cipher_text=cipher_text, + encryption_algorithm=encryption_algorithm, + key_id=key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.decrypt_data(request) + self.logger.info("Successfully decrypted data:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def encrypt_data(self,key_id=None,plain_text=None, encryption_algorithm=None, sequence=None, **kwargs): + try: + request = EncryptDataRequest() + request.body = EncryptDataRequestBody( + plain_text=plain_text, + key_id=key_id, + encryption_algorithm=encryption_algorithm, + sequence=sequence + ) + response = self.dew_client.kms_client.encrypt_data(request) + self.logger.info("Successfully encrypted data:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def sign(self,key_id=None, message=None, signing_algorithm=None, message_type=None, sequence=None, **kwargs): + try: + request = SignRequest() + request.body = SignRequestBody( + signing_algorithm=signing_algorithm, + message=message, + key_id=key_id, + message_type=message_type, + sequence=sequence + ) + response = self.dew_client.kms_client.sign(request) + self.logger.info("Successfully sign:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def validate_signature(self, key_id=None, message=None, signature=None, signing_algorithm=None, + message_type=None, sequence=None, **kwargs): + try: + request = ValidateSignatureRequest() + request.body = VerifyRequestBody( + key_id=key_id, + message=message, + signature=signature, + signing_algorithm=signing_algorithm, + message_type=message_type, + sequence=sequence + ) + response = self.dew_client.kms_client.validate_signature(request) + self.logger.info("Successfully list validate signature:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def list_key_detail(self,key_id=None,sequence=None, **kwargs): + try: + request = ListKeyDetailRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.list_key_detail(request) + self.logger.info("Successfully list key detail:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def list_keys(self,limit=None, marker=None, key_state=None, key_spec=None, + enterprise_project_id=None, sequence=None, **kwargs): + try: + request = ListKeysRequest() + request.body = ListKeysRequestBody( + limit=limit, + marker=marker, + key_state=key_state, + key_spec=key_spec, + enterprise_project_id=enterprise_project_id, + sequence=sequence + ) + response = self.dew_client.kms_client.list_keys(request) + self.logger.info(json.dumps(response.to_dict()).replace('}','}\n')) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def show_public_key(self,key_id=None, sequence=None, **kwargs): + try: + request = ShowPublicKeyRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.show_public_key(request) + self.logger.info("Successfully show public key:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def show_user_instances(self, **kwargs): + try: + request = ShowUserInstancesRequest() + response = self.dew_client.kms_client.show_user_instances(request) + self.logger.info("Successfully show user instances:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def show_user_quotas(self, **kwargs): + try: + request = ShowUserQuotasRequest() + response = self.dew_client.kms_client.show_user_quotas(request) + self.logger.info("Successfully show user quotas:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def show_version(self, **kwargs): + try: + request = ShowVersionRequest(kwargs) + response = self.dew_client.kms_client.show_version(request) + self.logger.info("Successfully show_version:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def show_versions(self, **kwargs): + try: + request = ShowVersionsRequest() + response = self.dew_client.kms_client.show_versions(request) + self.logger.info("Successfully show versions:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(e) + + def disable_key_rotation(self, key_id=None, sequence=None, **kwargs): + try: + request = DisableKeyRotationRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.disable_key_rotation(request) + self.logger.info("Successfully disable key rotation:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def enable_key_rotation(self, key_id=None, sequence=None, **kwargs): + try: + request = EnableKeyRotationRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.enable_key_rotation(request) + self.logger.info("Successfully enable key rotation:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def show_key_rotation_status(self, key_id=None, sequence=None, **kwargs): + try: + request = ShowKeyRotationStatusRequest() + request.body = OperateKeyRequestBody( + key_id=key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.show_key_rotation_status(request) + self.logger.info("Successfully show key rotation status:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def update_key_rotation_interval(self, key_id=None, rotation_interval=None, sequence=None, **kwargs): + try: + request = UpdateKeyRotationIntervalRequest() + request.body = UpdateKeyRotationIntervalRequestBody( + rotation_interval=rotation_interval, + key_id=key_id, + sequence=sequence + ) + response = self.dew_client.kms_client.update_key_rotation_interval(request) + self.logger.info("Successfully update key rotation interval:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def create_keypair(self,name=None, type=None, public_key=None, scope=None, user_id=None, key_protection=None, **kwargs): + try: + request = CreateKeypairRequest() + key_pair_body = CreateKeypairAction( + name=name, + type=type, + public_key=public_key, + scope=scope, + user_id=user_id, + key_protection=key_protection + ) + request.body = CreateKeypairRequestBody( + keypair=key_pair_body + ) + response = self.dew_client.kps_client.create_keypair(request) + self.logger.info("Successfully created keypair:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def list_keypairs(self,limit=None, marker=None, **kwargs): + try: + request = ListKeypairsRequest(limit=limit, marker=marker) + response = self.dew_client.kps_client.list_keypairs(request) + self.logger.info("Successfully list keypairs:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def clear_private_key(self, keypair_name=None, **kwargs): + try: + request = ClearPrivateKeyRequest(keypair_name=keypair_name) + response = self.dew_client.kps_client.clear_private_key(request) + self.logger.info("Successfully cleared private key:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def import_private_key(self, user_id=None, name=None,type="default", kms_key_name="kps/default", private_key=None, **kwargs): + try: + request = ImportPrivateKeyRequest() + encryption_key_protection = Encryption( + type=type, + kms_key_name=kms_key_name + ) + key_protection_keypair = ImportPrivateKeyProtection( + private_key=private_key, + encryption=encryption_key_protection + ) + key_pair_body = ImportPrivateKeyKeypairBean( + name=name, + key_protection=key_protection_keypair, + user_id=user_id + ) + request.body = ImportPrivateKeyRequestBody(keypair=key_pair_body) + response = self.dew_client.kps_client.import_private_key(request) + self.logger.info("Successfully import_private_key:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def list_keypair_detail(self, keypair_name=None, **kwargs): + try: + request = ListKeypairDetailRequest(keypair_name=keypair_name) + response = self.dew_client.kps_client.list_keypair_detail(request) + self.logger.info("Successfully list private key detail:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def list_keypairs(self, keypair_name=None, **kwargs): + try: + request = ListKeypairsRequest() + response = self.dew_client.kps_client.list_keypairs(request) + self.logger.info("Successfully list private keys:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def update_keypair_description(self, keypair_name=None, description=None, **kwargs): + try: + request = UpdateKeypairDescriptionRequest( + keypair_name=keypair_name + ) + key_pair_body = UpdateKeypairDescriptionReq( + description=description + ) + request.body = UpdateKeypairDescriptionRequestBody( + keypair=key_pair_body + ) + response = self.dew_client.kps_client.update_keypair_description(request) + self.logger.info("Successfully updated:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def export_private_key(self, name=None, **kwargs): + try: + request = ExportPrivateKeyRequest() + key_pair_body = KeypairBean(name=name) + request.body = ExportPrivateKeyRequestBody(keypair=key_pair_body) + response = self.dew_client.kps_client.export_private_key(request) + self.logger.info("Successfully exported private key:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def delete_keypair(self,keypair_name=None, **kwargs): + try: + request = DeleteKeypairRequest(keypair_name=keypair_name) + response = self.dew_client.kps_client.delete_keypair(request) + self.logger.info("Successfully deleted keypair") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def associate_keypair(self,keypair_name=None,type=None,key=None,id=None, disable_password=False, port=None, **kwargs): + try: + request = AssociateKeypairRequest() + auth_server = Auth(type=type, key=key) + server_body = EcsServerInfo( + id=id, + auth=auth_server, + disable_password=disable_password, + port=port + ) + request.body = AssociateKeypairRequestBody( + server=server_body, + keypair_name=keypair_name + ) + response = self.dew_client.kps_client.associate_keypair(request) + self.logger.info("Successfully associate_keypair:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def batch_associate_keypair(self, keypair_name=None, type=None, key=None, id=None, disable_password=None, port=None, **kwargs): + try: + request = BatchAssociateKeypairRequest() + list_batch_keypairs_body = [] + for s in range(len(keypair_name), **kwargs): + auth_server = Auth( + type=type[s], + key=key[s] + ) + server_satch_keypairs = EcsServerInfo( + id=id[s], + auth=auth_server, + disable_password=disable_password[s], + port=port[s] + ) + list_batch_keypairs_body.append(AssociateKeypairRequestBody( + keypair_name=keypair_name[s], + server=server_satch_keypairs + )) + + request.body = BatchAssociateKeypairRequestBody( + batch_keypairs=list_batch_keypairs_body + ) + response = self.dew_client.kps_client.batch_associate_keypair(request) + self.logger.info("Successfully batch_associate_keypair:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def delete_all_failed_task(self, **kwargs): + try: + request = DeleteAllFailedTaskRequest() + response = self.dew_client.kps_client.delete_all_failed_task(request) + self.logger.info("Successfully delete_all_failed_task:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def delete_failed_task(self, task_id, **kwargs): + try: + request = DeleteFailedTaskRequest( + task_id=task_id, + ) + response = self.dew_client.kps_client.delete_failed_task(request) + self.logger.info("Successfully delete_failed_task:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def disassociate_keypair(self, id=None, type=None, key=None, **kwargs): + try: + request = DisassociateKeypairRequest() + auth_server = Auth(type=type, key=key) + server_body = DisassociateEcsServerInfo(id=id, auth=auth_server) + request.body = DisassociateKeypairRequestBody(server=server_body) + response = self.dew_client.kps_client.disassociate_keypair(request) + self.logger.info("Successfully disassociate_keypair:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def list_failed_task(self, limit=None, offset=None, **kwargs): + try: + request = ListFailedTaskRequest() + request.limit = limit + request.offset = offset + response = self.dew_client.kps_client.list_failed_task(request) + self.logger.info("Successfully list_failed_task:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def list_keypair_task(self, task_id=None, **kwargs): + try: + request = ListKeypairTaskRequest(task_id=task_id) + response = self.dew_client.kps_client.list_keypair_task(request) + self.logger.info("Successfully list_keypair_task:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def list_running_task(self, limit=None, offset=None, **kwargs): + try: + request = ListRunningTaskRequest() + request.limit = limit + request.offset = offset + response = self.dew_client.kps_client.list_running_task(request) + self.logger.info("Successfully list_running_task:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def create_secret(self, name=None, kms_key_id=None, description=None, + secret_binary=None, secret_string=None, secret_type=None, + auto_rotation=None, rotation_period=None, rotation_config=None, + event_subscriptions=None, enterprise_project_id=None, **kwargs): + try: + request = CreateSecretRequest() + request.body = CreateSecretRequestBody( + secret_string=secret_string, + kms_key_id=kms_key_id, + name=name, + description=description, + secret_binary=secret_binary, + secret_type=secret_type, + auto_rotation=auto_rotation, + rotation_period=rotation_period, + rotation_config=rotation_config, + event_subscriptions=event_subscriptions, + enterprise_project_id=enterprise_project_id + ) + response = self.dew_client.cms_client.create_secret(request) + self.logger.info("Successfully create_secret:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def download_secret_blob(self, secret_name=None, **kwargs): + try: + request = DownloadSecretBlobRequest(secret_name=secret_name) + response = self.dew_client.cms_client.download_secret_blob(request) + self.logger.info("Successfully download_secret_blob:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def list_secrets(self, limit=None, marker=None, event_name=None, **kwargs): + try: + request = ListSecretsRequest() + request.limit = limit + request.marker = marker + request.event_name = event_name + response = self.dew_client.cms_client.list_secrets(request) + self.logger.info("Successfully list_secrets:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def show_secret(self, secret_name, **kwargs): + try: + request = ShowSecretRequest(secret_name=secret_name) + response = self.dew_client.cms_client.show_secret(request) + self.logger.info("Successfully show_secret:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def update_secret(self, kms_key_id=None, secret_name=None, description=None, + auto_rotation=None, rotation_period=None, listEventSubscriptionsbody=None, **kwargs): + try: + request = UpdateSecretRequest() + request.body = UpdateSecretRequestBody( + event_subscriptions=listEventSubscriptionsbody, + description=description, + kms_key_id=kms_key_id, + auto_rotation=auto_rotation, + rotation_period=rotation_period, + ) + request.secret_name=secret_name + response = self.dew_client.cms_client.update_secret(request) + self.logger.info("Successfully update_secret:") + + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def create_secret_event(self, target_type=None, target_id=None, + target_name=None, name=None, state=None, + listEventTypesbody=None, **kwargs): + try: + request = CreateSecretEventRequest() + notification_body = Notification( + target_type=target_type, + target_id=target_id, + target_name=target_name + ) + request.body = CreateSecretEventRequestBody( + notification=notification_body, + state=state, + event_types=listEventTypesbody, + name=name, + ) + response = self.dew_client.cms_client.create_secret_event(request) + self.logger.info("Successfully create_secret_event:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def upload_secret_blob(self, secret_blob, **kwargs): + try: + request = UploadSecretBlobRequest() + request.body = UploadSecretBlobRequestBody(secret_blob=secret_blob) + response = self.dew_client.cms_client.upload_secret_blob(request) + self.logger.info("Successfully upload_secret_blob:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(e.status_code) + self.logger.error(e.request_id) + self.logger.error(e.error_code) + + def rotate_secret(self,secret_name=None, **kwargs): + try: + request = RotateSecretRequest(secret_name=secret_name) + response = self.dew_client.cms_client.rotate_secret(request) + self.logger.info("Successfully rotate_secret:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def restore_secret(self,secret_name, **kwargs): + try: + request = RestoreSecretRequest(secret_name=secret_name) + response = self.dew_client.cms_client.restore_secret(request) + self.logger.info("Successfully restore_secret:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def delete_secret_for_schedule(self,recovery_window_in_days=None,secret_name=None, **kwargs): + try: + request = DeleteSecretForScheduleRequest(secret_name=secret_name) + request.body = DeleteSecretForScheduleRequestBody( + recovery_window_in_days=recovery_window_in_days + ) + response = self.dew_client.cms_client.delete_secret_for_schedule(request) + self.logger.info("Successfully delete_secret_for_schedule:") + + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def delete_secret(self,secret_name, **kwargs): + try: + request = DeleteSecretRequest(secret_name=secret_name) + response = self.dew_client.cms_client.delete_secret(request) + self.logger.info("Successfully delete_secret:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def create_secret_version(self,secret_name=None,secret_binary=None, + secret_string=None, version_stages=None, expire_time=None, **kwargs): + try: + request = CreateSecretVersionRequest(secret_name=secret_name) + request.body = CreateSecretVersionRequestBody( + secret_string=secret_string, + secret_binary=secret_binary, + version_stages=version_stages, + expire_time=expire_time + ) + response = self.dew_client.cms_client.create_secret_version(request) + self.logger.info("Successfully create_secret_version:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def list_secret_versions(self,secret_name=None, marker=None, limit=None, **kwargs): + try: + request = ListSecretVersionsRequest() + request.secret_name = secret_name + request.marker = marker + request.limit = limit + response = self.dew_client.cms_client.list_secret_versions(request) + self.logger.info("Successfully list_secret_versions:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def show_secret_version(self,secret_name=None,version_id=None, **kwargs): + try: + request = ShowSecretVersionRequest() + request.secret_name=secret_name + request.version_id = version_id + response = self.dew_client.cms_client.show_secret_version(request) + self.logger.info("Successfully show_secret_version:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + def update_version(self,secret_name=None, version_id=None, expire_time=None, **kwargs): + try: + request = UpdateVersionRequest() + request.version_id=version_id + request.secret_name=secret_name + request.body = UpdateVersionRequestBody( + expire_time=expire_time + ) + response = self.dew_client.cms_client.update_version(request) + self.logger.info("Successfully update_version:") + self.logger.info(response) + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ + error_code= {e.error_code}, error_msg= {e.error_msg}") + + diff --git a/build/lib/prefect_huaweicloud/dew_client.py b/build/lib/prefect_huaweicloud/dew_client.py new file mode 100644 index 0000000..7aa3751 --- /dev/null +++ b/build/lib/prefect_huaweicloud/dew_client.py @@ -0,0 +1,30 @@ +from huaweicloudsdkcore.auth.credentials import BasicCredentials +from huaweicloudsdkkms.v2.region.kms_region import KmsRegion +from huaweicloudsdkkms.v2 import KmsClient +from huaweicloudsdkkps.v3.region.kps_region import KpsRegion +from huaweicloudsdkkps.v3 import KpsClient +from huaweicloudsdkcsms.v1.region.csms_region import CsmsRegion +from huaweicloudsdkcsms.v1 import CsmsClient + + +class DewClient(): + def __init__(self,region_id=None, ak=None, sk=None, *args, **kwargs): + if not ak or not sk: + raise Exception("please input both huawei_cloud_access_key_id and huawei_cloud_secret_access_key") + self.region_id=region_id + self.__ak=ak + self.__sk=sk + self.kms_client=KmsClient.new_builder() \ + .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ + .with_region(KmsRegion.value_of(self.region_id)) \ + .build() + self.kps_client=KpsClient.new_builder() \ + .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ + .with_region(KpsRegion.value_of(self.region_id)) \ + .build() + self.cms_client=CsmsClient.new_builder() \ + .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ + .with_region(CsmsRegion.value_of(self.region_id)) \ + .build() + + \ No newline at end of file diff --git a/build/lib/prefect_huaweicloud/obs_block.py b/build/lib/prefect_huaweicloud/obs_block.py new file mode 100644 index 0000000..bea8e36 --- /dev/null +++ b/build/lib/prefect_huaweicloud/obs_block.py @@ -0,0 +1,364 @@ +import io +import json +import os +from logging import Logger +from typing import Optional +from pathlib import Path + +from obs import ObsClient + +from prefect.blocks.core import Block +from prefect.filesystems import WritableDeploymentStorage, WritableFileSystem +from pydantic import Field, SecretStr + +from prefect.utilities.asyncutils import sync_compatible, run_sync_in_worker_thread +from prefect.utilities.filesystem import filter_files +from prefect.logging.loggers import get_logger, get_run_logger +from prefect.exceptions import MissingContextError + + +class ObsBlock(WritableFileSystem, WritableDeploymentStorage, Block): + + + _logo_url = "https://res-static.hc-cdn.cn/cloudbu-site/public/header-icon/Storage/OBS.png" # noqa + _block_type_name = "HuaweiCloud Obs" + _documentation_url = ("https://support.huaweicloud.com/intl/zh-cn/sdk-python-devg-obs/obs_22_0100.html") # noqa + + huawei_cloud_access_key_id: Optional[SecretStr] = Field( + default=None, + description="A specific Huawei Cloud access key ID.", + title="Huawei Cloud Access Key ID", + ) + huawei_cloud_secret_access_key: Optional[SecretStr] = Field( + default=None, + description="A specific Huawei Cloud secret access key.", + title="Huawei Cloud Access Key Secret", + ) + huawei_cloud_security_token: Optional[SecretStr] = Field( + default=None, + description="SecurityToken in the temporary access key, " + "You can select a temporary token or AK/SK for authentication", + title="Huawei Cloud Security Token", + ) + end_point: str = Field( + default="https://obs.cn-south-1.myhuaweicloud.com", + description=( + "Service address for connecting to OBS. The value can contain the protocol type, domain name, " + "and port number. Example: https://your-endpoint:443. (For security purposes, HTTPS is recommended.)" + ), + title="End Point", + ) + bucket: str = Field( + default=None, + description=( + "Name of the bucket for creating a bucket client" + ), + title="Bucket", + ) + + prefix: Optional[str] = Field( + default=None, + description=( + "Name prefix that the objects to be listed must contain. example: xxx/xxx. prefix cannot start with /" + ), + title="Prefix", + ) + + extra_params: Optional[str] = Field( + default='{}', + description=( + "Additional parameters such as max_retry_count," + " max_redirect_count, and ssl_verify are written in JSON format," + " as shown in {'max_retry_count': 3,'max_redirect_count': 2}." + "Detailed link: https://support.huaweicloud.com/intl/en-us/sdk-python-devg-obs/obs_22_0601.html" + ), + title="Extra Params", + ) + + @property + def logger(self) -> Logger: + """ + Returns a logger based on whether the ObjectStorageBlock + is called from within a flow or task run context. + If a run context is present, the logger property returns a run logger. + Else, it returns a default logger labeled with the class's name. + + Returns: + The run logger or a default logger with the class's name. + """ + try: + return get_run_logger() + except MissingContextError: + return get_logger(self.__class__.__name__) + + @sync_compatible + async def read_path(self, path: str) -> bytes: + """ + Reading OBS File Objects + Args: + path: OBS File Object Key + + Returns: OBS File BytesIO + + """ + path = self._resolve_path(path) + return await run_sync_in_worker_thread(self._download_file_object, path) + + @sync_compatible + async def write_path(self, path: str, content: bytes) -> None: + """ + Writing a File Object to OBS + Args: + path: OBS Storage Path + content: File Object Flow + Returns: + + """ + path = self._resolve_path(path) + + await run_sync_in_worker_thread(self._upload_file_object, path, content) + + return path + + @sync_compatible + async def get_directory( + self, from_path: str = None, local_path: str = None + ) -> None: + """ + Download all files from the folder path in the OBS bucket to the local path. + Args: + from_path: obs dir path + local_path: local dir path + + Returns: + + """ + + folder_path = self.prefix if not self.prefix == "/" else None + if from_path is None: + from_path = str(folder_path) if folder_path else None + + if local_path is None: + local_path = str(Path("..").absolute()) + else: + local_path = str(Path(local_path).expanduser()) + obs_client = self._get_obs_client() + for path, is_dir in self._bucket_list_object(from_path): + self.logger.info(path) + target_path = os.path.join( + local_path, + path + ) + target_path = os.path.normpath(target_path) + if is_dir: + os.makedirs(target_path, exist_ok=True) + continue + try: + resp = obs_client.getObject(self.bucket, path, downloadPath=target_path) + if resp.status < 300: + self.logger.info('requestId: %s', resp.requestId) + else: + self.logger.error('errorCode: %s', resp.errorCode) + self.logger.error('errorMessage: %s', resp.errorMessage) + except Exception as e: + import traceback + self.logger.error(traceback.format_exc()) + + @sync_compatible + async def put_directory( + self, local_path: str = None, to_path: str = None, ignore_file: str = None + ) -> int: + """ + Pushes all files in the local folder to the specified folder in the OBS bucket. + + Args: + local_path: Path to local directory to upload from. + to_path: Path in OBS bucket to upload to. Defaults to block's configured + basepath. + ignore_file: Path to file containing gitignore style expressions for + filepaths to ignore. + Returns: + + """ + + if local_path is None: + raise Exception("local_path can't be None") + + local_path = os.path.normpath(local_path) + included_files = None + if ignore_file: + with open(ignore_file, "r") as f: + ignore_patterns = f.readlines() + + included_files = filter_files(local_path, ignore_patterns) + + uploaded_file_count = 0 + for local_file_path in Path(local_path).expanduser().rglob("*"): + if ( + included_files is not None + and str(local_file_path.relative_to(local_path)) not in included_files + ): + continue + elif not local_file_path.is_dir(): + remote_file_path = Path(to_path) / local_file_path.relative_to( + local_path + ) + with open(local_file_path, "rb") as local_file: + local_file_content = local_file.read() + + await self.write_path( + path=remote_file_path.as_posix(), content=local_file_content + ) + uploaded_file_count += 1 + + return uploaded_file_count + + def _get_obs_client(self) -> ObsClient: + """ + The authenticated OBS client is returned. You can select a temporary token or AK/SK for authentication. + Returns: ObsClient + """ + extra_params = json.loads(self.extra_params) + + if self.huawei_cloud_security_token: + return ObsClient( + security_token=self.huawei_cloud_security_token.get_secret_value(), + server=self.end_point, + **extra_params + ) + if not self.huawei_cloud_access_key_id or not self.huawei_cloud_secret_access_key: + raise Exception("please input both huawei_cloud_access_key_id and huawei_cloud_secret_access_key") + + return ObsClient( + access_key_id=self.huawei_cloud_access_key_id.get_secret_value(), + secret_access_key=self.huawei_cloud_secret_access_key.get_secret_value(), + server=self.end_point, + **extra_params + ) + + def _resolve_path(self, path): + """ + Concatenate the file object path based on the preset path prefix. + + Args: + path: Path before splicing + + Returns: Path after splicing + + """ + + path = ( + (Path(self.prefix) / path).as_posix() if self.prefix else path + ) + + return path + + def _download_file_object_inner(self, obs_client, key, stream): + resp = obs_client.getObject(self.bucket, key, loadStreamInMemory=False) + + if resp.status < 300: + self.logger.info('requestId: %s', resp.requestId) + # 读取对象内容 + while True: + chunk = resp.body.response.read(65536) + if not chunk: + break + stream.write(chunk) + resp.body.response.close() + else: + self.logger.error('errorCode: %s', resp.errorCode) + self.logger.error('errorMessage: %s', resp.errorMessage) + + def _download_file_object(self, key: str): + """ + Downloading a File Object from OBS + + Args: + key: OBS File Object Key + + Returns: OBS File BytesIO + + """ + obs_client = self._get_obs_client() + with io.BytesIO() as stream: + try: + self._download_file_object_inner(obs_client, key, stream) + except Exception as e: + import traceback + self.logger.error(traceback.format_exc()) + stream.seek(0) + output = stream.read() + obs_client.close() + return output + + def _upload_file_object(self, path: str, data: bytes) -> None: + """ + Uploading a File Object to OBS + Args: + path: OBS Storage Path + data: File Object Flow + + Returns: + + """ + obs_client = self._get_obs_client() + try: + + resp = obs_client.putContent(self.bucket, path, content=data) + + if resp.status < 300: + self.logger.info('requestId: %s', resp.requestId) + else: + self.logger.error('errorCode: %s', resp.errorCode) + self.logger.error('errorMessage: %s', resp.errorMessage) + except Exception as e: + import traceback + self.logger.error(traceback.format_exc()) + + def _bucket_list_object_inner(self, obs_client, prefix, mark, max_num): + object_list = [] + resp = obs_client.listObjects(self.bucket, prefix=prefix, marker=mark, max_keys=max_num) + self.logger.info(resp) + if resp.status < 300: + self.logger.info('requestId: %s', resp.requestId) + index = 1 + for content in resp.body.contents: + self.logger.info('object [%s]', str(index)) + index += 1 + if content.size == 0: + object_list.append((content.key, True)) + else: + object_list.append((content.key, False)) + if resp.body.is_truncated is True: + return object_list, False, resp.body.next_marker + else: + return object_list, True, resp.body.next_marker + else: + self.logger.error('errorCode: %s', resp.errorCode) + self.logger.error('errorMessage: %s', resp.errorMessage) + return [], True, False + + def _bucket_list_object(self, prefix): + """ + Querying All Objects in a Bucket + Args: + prefix: Path Prefix + + Returns: file object key and is dir bool + + """ + obs_client = self._get_obs_client() + max_num = 1000 + mark = None + all_object_list = [] + is_break = False + try: + while not is_break: + object_list, is_break, mark = self._bucket_list_object_inner(obs_client, prefix, mark, max_num) + all_object_list.extend(object_list) + except Exception as e: + import traceback + self.logger.error(traceback.format_exc()) + finally: + obs_client.close() + return all_object_list diff --git a/build/lib/prefect_huaweicloud/test/__init__.py b/build/lib/prefect_huaweicloud/test/__init__.py new file mode 100644 index 0000000..3f591f7 --- /dev/null +++ b/build/lib/prefect_huaweicloud/test/__init__.py @@ -0,0 +1,3 @@ +from prefect_huaweicloud.obs_block import ObsBlock +from prefect_huaweicloud.dew_block import DewBlock +__all__ = ["ObsBlock","DewBlock"] \ No newline at end of file diff --git a/build/lib/prefect_huaweicloud/test/test_dew_block.py b/build/lib/prefect_huaweicloud/test/test_dew_block.py new file mode 100644 index 0000000..fc955c1 --- /dev/null +++ b/build/lib/prefect_huaweicloud/test/test_dew_block.py @@ -0,0 +1,153 @@ +import sys +from pathlib import Path +sys.path.append(str(Path(__file__).resolve().parents[1])) +from dew_block import DewBlock +from prefect import flow,task + + +def kms_params(huaweicloud_dew_block, key_alias=None,key_spec=None): + test_key=huaweicloud_dew_block.create_key(key_alias=key_alias) + return dict( + key_alias=key_alias, + key_id=test_key.key_info.key_id, + key_description=None, + pending_days=7, + random_data_length=512, + datakey_length=512, + datakey_plain_length=64, + datakey_cipher_length=64, + cipher_text=None, + plain_text=None, + datakey_dgst=None, + + grantee_principal="0f9eaeef3b7347f3804c2b27d126273e", + listOperationsbody = [ + "describe-key", + "create-datakey", + "encrypt-datakey"], + grant_id=None, + encryption_algorithm="SYMMETRIC_DEFAULT", + rotation_interval=30, + + signing_algorithm="RSASSA_PKCS1_V1_5_SHA_256", + message="09d158717e34db02afbe64c1d96b7a7cb3e846fb04f642b6257caccf1ca06485", + message_type="RAW", + signature=None + + ) + + +def kps_params(huaweicloud_dew_block, name): + key_pair_list=huaweicloud_dew_block.list_keypairs() + if name in list(x.keypair.name for x in key_pair_list.keypairs[:]): + huaweicloud_dew_block.delete_keypair(keypair_name=name) + test_key=huaweicloud_dew_block.create_keypair(name=name) + return dict( + name=name, + keypair_name=name, + private_key=test_key.keypair.private_key, + description=None + ) + + +@flow +def test_key_lifecycle_management(kms_params, huaweicloud_dew_block): + row_key_alias=kms_params['key_alias'] + huaweicloud_dew_block.create_key(**kms_params) + huaweicloud_dew_block.disable_key(**kms_params) + huaweicloud_dew_block.enable_key(**kms_params) + kms_params['key_alias']="test_alias" + huaweicloud_dew_block.update_key_Alias(**kms_params) + kms_params['key_alias']=row_key_alias + huaweicloud_dew_block.update_key_Alias(**kms_params) + kms_params['key_description']="test_update_description" + huaweicloud_dew_block.update_key_description(**kms_params) + huaweicloud_dew_block.delete_key(**kms_params) + huaweicloud_dew_block.cancel_key_deletion(**kms_params) + huaweicloud_dew_block.enable_key(**kms_params) + + +@flow +def test_data_key_management(kms_params, huaweicloud_dew_block): + huaweicloud_dew_block.create_data_key_without_plaintext(**kms_params) + create_data_key_response=huaweicloud_dew_block.create_data_key(**kms_params) + huaweicloud_dew_block.create_random(**kms_params) + kms_params["cipher_text"]=create_data_key_response.cipher_text + decrypt_data_key_response=huaweicloud_dew_block.decrypt_data_key(**kms_params) + kms_params["datakey_dgst"]=decrypt_data_key_response.datakey_dgst + kms_params["plain_text"]=decrypt_data_key_response.data_key+decrypt_data_key_response.datakey_dgst + huaweicloud_dew_block.encrypt_data_key(**kms_params) + + +@flow +def test_key_grant_management(kms_params, huaweicloud_dew_block): + create_grant_response=huaweicloud_dew_block.create_grant(**kms_params) + kms_params["grant_id"]=create_grant_response.grant_id + huaweicloud_dew_block.list_retirable_grants(**kms_params) + # huaweicloud_dew_block.cancel_self_grant(**kms_params) + huaweicloud_dew_block.cancel_grant(**kms_params) + huaweicloud_dew_block.list_grants(**kms_params) + + +@flow +def test_key_pair_management(kps_params, huaweicloud_dew_block): + row_keypair_name=kps_params['name'] + huaweicloud_dew_block.import_private_key(**kps_params) + huaweicloud_dew_block.export_private_key(**kps_params) + huaweicloud_dew_block.list_keypair_detail(**kps_params) + huaweicloud_dew_block.list_keypairs(**kps_params) + huaweicloud_dew_block.clear_private_key(**kps_params) + + kps_params['description']="test_update_description" + huaweicloud_dew_block.update_keypair_description(**kps_params) + + huaweicloud_dew_block.delete_keypair(**kps_params) + + +@flow +def test_small_data_encryption(kms_params, huaweicloud_dew_block): + encrypt_data_response=huaweicloud_dew_block.encrypt_data(**kms_params) + kms_params["cipher_text"]=encrypt_data_response.cipher_text + huaweicloud_dew_block.decrypt_data(**kms_params) + + + +@flow +def test_list_key(kms_params, huaweicloud_dew_block): + huaweicloud_dew_block.list_keys(**kms_params) + huaweicloud_dew_block.list_key_detail(**kms_params) + huaweicloud_dew_block.show_public_key(key_id="95afc13e-a5ed-4271-b8e9-a71079e8c6b3") + huaweicloud_dew_block.show_user_instances(**kms_params) + huaweicloud_dew_block.show_user_quotas(**kms_params) + + +@flow +def test_key_rotation_management(kms_params, huaweicloud_dew_block): + huaweicloud_dew_block.enable_key_rotation(**kms_params) + huaweicloud_dew_block.show_key_rotation_status(**kms_params) + huaweicloud_dew_block.update_key_rotation_interval(**kms_params) + huaweicloud_dew_block.disable_key_rotation(**kms_params) + + +@flow +def test_signature_verification(kms_params,huaweicloud_dew_block): + kms_params["key_id"]="95afc13e-a5ed-4271-b8e9-a71079e8c6b3" + row_sign=huaweicloud_dew_block.sign(**kms_params) + kms_params['signature']=row_sign.signature + huaweicloud_dew_block.validate_signature(**kms_params) + + + +if __name__=="__main__": + huaweicloud_dew_block = DewBlock.load("test-dew-block") + kms_params=kms_params(huaweicloud_dew_block, key_alias="1-9") + kps_params=kps_params(huaweicloud_dew_block, name="22-22") +# test_key_lifecycle_management(kms_params,huaweicloud_dew_block) + test_key_pair_management(kps_params,huaweicloud_dew_block) +# test_data_key_management(kms_params,huaweicloud_dew_block) +# test_key_grant_management(kms_params,huaweicloud_dew_block) +# test_small_data_encryption(kms_params,huaweicloud_dew_block) +# test_list_key(kms_params, huaweicloud_dew_block) +# test_key_rotation_management(kms_params, huaweicloud_dew_block) +# test_signature_verification(kms_params, huaweicloud_dew_block) + \ No newline at end of file diff --git a/build/lib/prefect_huaweicloud/test_dew.py b/build/lib/prefect_huaweicloud/test_dew.py new file mode 100644 index 0000000..10bfa6e --- /dev/null +++ b/build/lib/prefect_huaweicloud/test_dew.py @@ -0,0 +1,111 @@ +from prefect_huaweicloud.dew_block import DewBlock + +from prefect import flow,task + +def kms_params(huaweicloud_dew_block,key_alias=None): + test_key=huaweicloud_dew_block.create_key(key_alias=key_alias) + return dict( + key_alias=key_alias, + key_id=test_key.key_info.key_id, + key_description=None, + pending_days=7, + random_data_length=512, + datakey_length=512, + datakey_plain_length=64, + datakey_cipher_length=64, + cipher_text=None, + plain_text=None, + datakey_dgst=None, + + grantee_principal="0f9eaeef3b7347f3804c2b27d126273e", + listOperationsbody = [ + "describe-key", + "create-datakey", + "encrypt-datakey"], + grant_id=None, + encryption_algorithm="SYMMETRIC_DEFAULT" + ) + + +def kps_params(huaweicloud_dew_block,name): + key_pair_list=huaweicloud_dew_block.list_keypairs() + if name in list(x.keypair.name for x in key_pair_list.keypairs[:]): + huaweicloud_dew_block.delete_keypair(keypair_name=name) + test_key=huaweicloud_dew_block.create_keypair(name=name) + return dict( + name=name, + keypair_name=name, + private_key=test_key.keypair.private_key, + # key_id=test_key.keypair.user_id, + description=None + ) + +@flow +def test_key_lifecycle_management(kms_params,huaweicloud_dew_block): + row_key_alias=kms_params['key_alias'] + huaweicloud_dew_block.create_key(**kms_params) + huaweicloud_dew_block.disable_key(**kms_params) + huaweicloud_dew_block.enable_key(**kms_params) + kms_params['key_alias']="test_alias" + huaweicloud_dew_block.update_key_Alias(**kms_params) + kms_params['key_alias']=row_key_alias + huaweicloud_dew_block.update_key_Alias(**kms_params) + kms_params['key_description']="test_update_description" + huaweicloud_dew_block.update_key_description(**kms_params) + huaweicloud_dew_block.delete_key(**kms_params) + huaweicloud_dew_block.cancel_key_deletion(**kms_params) + huaweicloud_dew_block.enable_key(**kms_params) + +@flow +def test_data_key_management(kms_params,huaweicloud_dew_block): + huaweicloud_dew_block.create_data_key_without_plaintext(**kms_params) + create_data_key_response=huaweicloud_dew_block.create_data_key(**kms_params) + huaweicloud_dew_block.create_random(**kms_params) + kms_params["cipher_text"]=create_data_key_response.cipher_text + decrypt_data_key_response=huaweicloud_dew_block.decrypt_data_key(**kms_params) + kms_params["datakey_dgst"]=decrypt_data_key_response.datakey_dgst + kms_params["plain_text"]=decrypt_data_key_response.data_key+decrypt_data_key_response.datakey_dgst + huaweicloud_dew_block.encrypt_data_key(**kms_params) + + +@flow +def test_key_grant_management(kms_params,huaweicloud_dew_block): + create_grant_response=huaweicloud_dew_block.create_grant(**kms_params) + kms_params["grant_id"]=create_grant_response.grant_id + huaweicloud_dew_block.list_retirable_grants(**kms_params) + # huaweicloud_dew_block.cancel_self_grant(**kms_params) + huaweicloud_dew_block.cancel_grant(**kms_params) + huaweicloud_dew_block.list_grants(**kms_params) + + + + + +@flow +def test_key_pair_management(kps_params,huaweicloud_dew_block): + row_keypair_name=kps_params['name'] + huaweicloud_dew_block.import_private_key(**kps_params) + huaweicloud_dew_block.export_private_key(**kps_params) + huaweicloud_dew_block.list_keypair_detail(**kps_params) + huaweicloud_dew_block.clear_private_key(**kps_params) + + kps_params['description']="test_update_description" + huaweicloud_dew_block.update_keypair_description(**kps_params) + + huaweicloud_dew_block.delete_keypair(**kps_params) + +def test_small_data_encryption(kms_params,huaweicloud_dew_block): + encrypt_data_response=huaweicloud_dew_block.encrypt_data(**kms_params) + kms_params["cipher_text"]=encrypt_data_response.cipher_text + huaweicloud_dew_block.decrypt_data(**kms_params) + + +if __name__=="__main__": + huaweicloud_dew_block = DewBlock.load("test-dew-block") + kms_params=kms_params(huaweicloud_dew_block,key_alias="12-26") +# test_key_lifecycle_management(kms_params,huaweicloud_dew_block) +# test_key_pair_management(kps_params(huaweicloud_dew_block,name="22-22"),huaweicloud_dew_block) + test_data_key_management(kms_params,huaweicloud_dew_block) +# test_key_grant_management(kms_params,huaweicloud_dew_block) + test_small_data_encryption(kms_params,huaweicloud_dew_block) + \ No newline at end of file diff --git a/dist/prefect_hwc-0.1.0-py3.11.egg b/dist/prefect_hwc-0.1.0-py3.11.egg new file mode 100644 index 0000000000000000000000000000000000000000..1241b50da91171daa12f1d5ed8ba5e85b53c7000 GIT binary patch literal 42312 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 J?%n;n{{b}s!AAf9 literal 0 HcmV?d00001 diff --git a/prefect_huaweicloud/__init__.py b/prefect_huaweicloud/__init__.py index e5be0e0..4064758 100644 --- a/prefect_huaweicloud/__init__.py +++ b/prefect_huaweicloud/__init__.py @@ -1,5 +1,6 @@ # ensure core blocks are registered from prefect_huaweicloud.obs_block import ObsBlock +from prefect_huaweicloud.dew_block import DewBlock -__all__ = ["ObsBlock"] +__all__ = ["ObsBlock","DewBlock"] diff --git a/prefect_huaweicloud/__pycache__/dew_block.cpython-311.pyc b/prefect_huaweicloud/__pycache__/dew_block.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07b093f51fbd95f8153a3a59b6150688f62fd830 GIT binary patch literal 134130 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℘-!v}b-Ee@<18}0i!<{AOLc}pZ=MgOBt}7~ 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 literal 0 HcmV?d00001 diff --git a/prefect_huaweicloud/__pycache__/dew_client.cpython-311.pyc b/prefect_huaweicloud/__pycache__/dew_client.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ad64ba43df7491f85e4df5fff8e46edb1ed0e235 GIT binary patch literal 2595 zcmd5;&2Jk;6rWvx#A|2cG)*JyDybm_)sPqxE{M8-a1aM1gMcbxu^4T3C(XvY_I73+ zlgft*^$@Du%LOT?5R_gkao~TzMvG*vROP^ln^EA>6Em~kjW-EWFOm8@JM(_?KK9L< zd9(gWmeYXJliv=|R|x?AWFVmUkU4fJ^9blb7ffIYiXbpvG({_>#5f-_<5ogRa6WD( ztubYc^9eI$Ns7ezq?xudN`~`e=C~y*vH(QzG0;;FfG+Ke036cCCuKrUe*ub_zZfhE z-sFcWF|-OsI%+tEY7#mpePWT%(H*1N7=nsvP$>uYsKh3rBwZmRMjZJvZTMn71YsP{ zQ1}QSpa?opL_Ma94+JHq3pBL2C#|5iZ(P-aR59};eX{g9{w&6;3+NZ-|0KguL;S4z}sv&j2=81o> z8G4UyLo~|0RA4JK9u*U$VdRWx6)$_zN8f75cIaK=NtoX$)YO}RVTnVi)}xrzG1~zz z(?D&w)-p^TVQ;c+I2(}q5AG?gW)l% zfmsRDSv#C%b&pvIdTA}xEhfDc_DU!MuSMeR3JYh+<8r%lG3h z+1p+ULZe|g5Z;>#b5{!HSgn(H=)G_s^s|=+K#+*=!<0Whow?R6-0jU^cLsMSaX8o!3tzLfF z%`ZPkq<1v=n4*0C+%9jjJygLe1B-$1;SxH16$)A>%AeYKeN=0}bI z(d$|hqmtTkHcDsC{%cW9ddy2(%O$@SO6<^&mc{gW%6^@l_G42&Z-;(pnGF5#x;gEK zEAzVYZbV<9(LV&Gt);*bgMlYrYgf)y$GjMMGOx3Y7Ffp;{47=Wx8gm#Kq31Ek|(qq y!~{X;gAcmV)(7QowDrO3-DrD0o%g#S()wVb8*PK+lt8!lZ1*>t`{x`1U)FzZc38Cl literal 0 HcmV?d00001 diff --git a/prefect_hwc.egg-info/PKG-INFO b/prefect_hwc.egg-info/PKG-INFO new file mode 100644 index 0000000..e948850 --- /dev/null +++ b/prefect_hwc.egg-info/PKG-INFO @@ -0,0 +1,29 @@ +Metadata-Version: 2.1 +Name: prefect-hwc +Version: 0.1.0 +Summary: Prefect collection of tasks and sub flows to integrate with HuaweiCloud +Home-page: https://gitee.com/HuaweiCloudDeveloper/huaweicloud-prefect-block-python +Author: HuaweiCloud +Author-email: +License: Apache License 2.0 +Keywords: prefect +Requires-Python: >=3.9 +Description-Content-Type: text/markdown + +# Prefect Huawei Cloud Block + +## Welcome! +The prefect-hwc collection enables you to use HUAWEI CLOUD service capabilities in Prefect more efficiently. +## Getting Started + +```bash +pip install -U "prefect" + +pip install prefect-hwc + +prefect block register --module prefect-hwc +``` + +## Contributing + +Thank you for wanting to contribute, you can contribute to [this code repository](https://gitee.com/HuaweiCloudDeveloper/huaweicloud-prefect-block-python) .If you have any questions, consult the community. diff --git a/prefect_hwc.egg-info/SOURCES.txt b/prefect_hwc.egg-info/SOURCES.txt new file mode 100644 index 0000000..4592988 --- /dev/null +++ b/prefect_hwc.egg-info/SOURCES.txt @@ -0,0 +1,14 @@ +README.md +setup.py +prefect_huaweicloud/__init__.py +prefect_huaweicloud/dew_block.py +prefect_huaweicloud/dew_client.py +prefect_huaweicloud/obs_block.py +prefect_huaweicloud/test_dew.py +prefect_huaweicloud/test/__init__.py +prefect_huaweicloud/test/test_dew_block.py +prefect_hwc.egg-info/PKG-INFO +prefect_hwc.egg-info/SOURCES.txt +prefect_hwc.egg-info/dependency_links.txt +prefect_hwc.egg-info/requires.txt +prefect_hwc.egg-info/top_level.txt \ No newline at end of file diff --git a/prefect_hwc.egg-info/dependency_links.txt b/prefect_hwc.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/prefect_hwc.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/prefect_hwc.egg-info/requires.txt b/prefect_hwc.egg-info/requires.txt new file mode 100644 index 0000000..ff1be1f --- /dev/null +++ b/prefect_hwc.egg-info/requires.txt @@ -0,0 +1,3 @@ +pydantic==1.10.11 +esdk-obs-python +prefect>=2.10.11 diff --git a/prefect_hwc.egg-info/top_level.txt b/prefect_hwc.egg-info/top_level.txt new file mode 100644 index 0000000..d32e0ca --- /dev/null +++ b/prefect_hwc.egg-info/top_level.txt @@ -0,0 +1 @@ +prefect_huaweicloud -- Gitee From 64eca3a38c76c95e1ee52cf6c551ea8d69b3228e Mon Sep 17 00:00:00 2001 From: Lky0312 <523175094@qq.com> Date: Sat, 24 Feb 2024 19:35:32 +0800 Subject: [PATCH 05/11] Improved interactivity between test scripts and effects --- .idea/.gitignore | 3 + .idea/huaweicloud-prefect-block-python.iml | 10 + .idea/inspectionProfiles/Project_Default.xml | 6 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + build/lib/prefect_huaweicloud/__init__.py | 4 +- build/lib/prefect_huaweicloud/dew_block.py | 2040 +++++++++++++---- build/lib/prefect_huaweicloud/dew_client.py | 23 +- .../lib/prefect_huaweicloud/test/__init__.py | 3 +- .../test/test_dew_block.py | 298 ++- dist/prefect_hwc-0.1.0-py3.12.egg | Bin 0 -> 43323 bytes prefect_huaweicloud/__init__.py | 4 +- .../__pycache__/dew_block.cpython-312.pyc | Bin 0 -> 130499 bytes .../__pycache__/dew_client.cpython-312.pyc | Bin 0 -> 2515 bytes prefect_huaweicloud/dew_block.py | 38 +- prefect_huaweicloud/dew_client.py | 11 +- prefect_huaweicloud/test/__init__.py | 3 +- prefect_huaweicloud/test/test_dew_block.py | 211 +- prefect_hwc.egg-info/SOURCES.txt | 1 - 21 files changed, 2028 insertions(+), 651 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/huaweicloud-prefect-block-python.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 dist/prefect_hwc-0.1.0-py3.12.egg create mode 100644 prefect_huaweicloud/__pycache__/dew_block.cpython-312.pyc create mode 100644 prefect_huaweicloud/__pycache__/dew_client.cpython-312.pyc diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..359bb53 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml diff --git a/.idea/huaweicloud-prefect-block-python.iml b/.idea/huaweicloud-prefect-block-python.iml new file mode 100644 index 0000000..74d515a --- /dev/null +++ b/.idea/huaweicloud-prefect-block-python.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..85a34ff --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..6f57296 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..91203d5 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/build/lib/prefect_huaweicloud/__init__.py b/build/lib/prefect_huaweicloud/__init__.py index 4064758..6710c4a 100644 --- a/build/lib/prefect_huaweicloud/__init__.py +++ b/build/lib/prefect_huaweicloud/__init__.py @@ -2,5 +2,5 @@ from prefect_huaweicloud.obs_block import ObsBlock from prefect_huaweicloud.dew_block import DewBlock - -__all__ = ["ObsBlock","DewBlock"] +from prefect_huaweicloud.dew_client import DewClient +__all__ = ["ObsBlock","DewBlock","DewClient"] diff --git a/build/lib/prefect_huaweicloud/dew_block.py b/build/lib/prefect_huaweicloud/dew_block.py index ff8174f..799a053 100644 --- a/build/lib/prefect_huaweicloud/dew_block.py +++ b/build/lib/prefect_huaweicloud/dew_block.py @@ -1,9 +1,7 @@ - -from typing import Optional +from typing import Optional, Dict, Any from logging import Logger from pydantic import Field, SecretStr from prefect.blocks.abstract import Block -from prefect.utilities.asyncutils import run_sync_in_worker_thread, sync_compatible from prefect.logging.loggers import get_logger, get_run_logger from prefect.exceptions import MissingContextError from prefect import task @@ -27,31 +25,41 @@ class DewBlock(Block): _documentation_url = ("https://support.huaweicloud.com/intl/zh-cn/sdk-python-devg-obs/obs_22_0100.html") # noqa huawei_cloud_access_key_id: Optional[SecretStr] = Field( - default=None, - description="A specific Huawei Cloud access key ID.", - title="Huawei Cloud Access Key ID:", + default = None, + description = "A specific Huawei Cloud access key ID.", + title = "Huawei Cloud Access Key ID:", ) huawei_cloud_secret_access_key: Optional[SecretStr] = Field( + default = None, + description = "A specific Huawei Cloud secret access key.", + title = "Huawei Cloud Access Key Secret:", + ) + huawei_cloud_project_id: Optional[SecretStr] = Field( default=None, - description="A specific Huawei Cloud secret access key.", - title="Huawei Cloud Access Key Secret:", + description = "A specific Huawei Cloud project id.", + title="Huawei Cloud project id", ) huawei_cloud_security_token: Optional[SecretStr] = Field( - default=None, - description="SecurityToken in the temporary access key, " + default = None, + description = "SecurityToken in the temporary access key, " "You can select a temporary token or AK/SK for authentication", - title="Huawei Cloud Security Token", + title = "Huawei Cloud Security Token", ) region_id:Optional[str] = Field( - default=None, - title="region id", + default = None, + title = "region id", ) - - def __init__(self,*args, **kwargs): - self.dew_client=DewClient(region_id=kwargs['region_id'], - ak=kwargs['huawei_cloud_access_key_id'], - sk=kwargs['huawei_cloud_secret_access_key']) - + huawei_cloud_dew_parameters: Optional[Dict[str, Any]] = Field( + default=None, + description="Extra parameters for using dew.", + title="dew_parameters", + ) + def __init__(self, *args, **kwargs): + self.dew_client = DewClient(region_id = kwargs['region_id'], + ak = kwargs['huawei_cloud_access_key_id'], + sk = kwargs['huawei_cloud_secret_access_key'], + project_id = kwargs['huawei_cloud_project_id'] if kwargs.get('huawei_cloud_project_id') else None) + self.dew_parameters = kwargs['huawei_cloud_dew_parameters'] if kwargs.get('huawei_cloud_project_id') else None @property def logger(self) -> Logger: """ @@ -68,176 +76,279 @@ class DewBlock(Block): except MissingContextError: return get_logger(self.__class__.__name__) - def create_key(self,key_alias=None, key_spec=None, key_usage=None, key_description=None, - origin=None, enterprise_project_id=None, sequence=None, keystore_id=None, **kwargs): + def create_key(self, key_alias = None, key_spec = None, key_usage = None, key_description = None, + origin = None, enterprise_project_id = None, sequence = None, keystore_id = None, **kwargs): + """ + Create a user master key, which can be a symmetric or asymmetric key. + + Args: + Key_ Alias: Non default master key alias, with a value range of 1 to 255 characters, satisfying + regular matching "^ [a-zA-Z0-9:/_ -] {1255} $", and not having the same name as the default + master key alias created by the system service. + type key_alias: str + """ try: request = CreateKeyRequest() request.body = CreateKeyRequestBody( - key_alias=key_alias, - key_spec=key_spec, - key_usage=key_usage, - key_description=key_description, - origin=origin, - enterprise_project_id=enterprise_project_id, - sequence=sequence, - keystore_id=keystore_id + key_alias = key_alias, + key_spec = key_spec, + key_usage = key_usage, + key_description = key_description, + origin = origin, + enterprise_project_id = enterprise_project_id, + sequence = sequence, + keystore_id = keystore_id ) - response =self.dew_client.kms_client.create_key(request) + response = self.dew_client.kms_client.create_key(request) self.logger.debug("Created key") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def delete_key(self,key_id=None,pending_days=None, sequence=None, **kwargs): + def delete_key(self, key_id = None, pending_days = None, sequence = None, **kwargs): + """ + How many days do you plan to delete the key? The key can be deleted within 7-1096 days. + + Args: + key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + :pending_days: How many days do you plan to delete the key, with values ranging from 7 to 1096. + :type pending_days: str + """ try: request = DeleteKeyRequest() request.body = ScheduleKeyDeletionRequestBody( - key_id=key_id, - pending_days=pending_days, - sequence=sequence + key_id = key_id, + pending_days = pending_days, + sequence = sequence ) response = self.dew_client.kms_client.delete_key(request) self.logger.debug("Successfully delete_key") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def disable_key(self,key_id=None,sequence=None, **kwargs): + def disable_key(self, key_id = None, sequence = None, **kwargs): + """ + Disabled key, cannot be used after disabling the key. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + """ try: request = DisableKeyRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) - response =self.dew_client.kms_client.disable_key(request) + response = self.dew_client.kms_client.disable_key(request) self.logger.info("Successfully disable_key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def enable_key(self,key_id=None, sequence=None, **kwargs): + def enable_key(self, key_id = None, sequence = None, **kwargs): + """ + Enable the key, which can only be used after it is enabled. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + """ try: request = EnableKeyRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) - response =self.dew_client.kms_client.enable_key(request) + response = self.dew_client.kms_client.enable_key(request) self.logger.info("Successfully enable_key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def update_key_Alias(self,key_id=None, key_alias=None, sequence=None, **kwargs): + def update_key_Alias(self, key_id = None, key_alias = None, sequence = None, **kwargs): + """ + Modify the user master key alias + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + :key_alias: Non default master key alias, ranging from 1 to 255 characters, satisfies regular matching + "^[a-zA-Z0-9:/_-]{1,255}$"and cannot have the suffix "/default". + :type key_alias: str + """ try: request = UpdateKeyAliasRequest() request.body = UpdateKeyAliasRequestBody( - key_alias=key_alias, - key_id=key_id, - sequence=sequence + key_alias = key_alias, + key_id = key_id, + sequence = sequence ) - response =self.dew_client.kms_client.update_key_alias(request) + response = self.dew_client.kms_client.update_key_alias(request) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def update_key_description(self,key_id=None, key_description=None, sequence=None, **kwargs): + def update_key_description(self, key_id = None, key_description = None, sequence = None, **kwargs): + """ + Modify user master key description information. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + :key_description: Key description, ranging from 0 to 255 characters. + :type key_description: str + """ try: request = UpdateKeyDescriptionRequest() request.body = UpdateKeyDescriptionRequestBody( - key_id=key_id, - key_description=key_description, - sequence=sequence + key_id = key_id, + key_description = key_description, + sequence = sequence ) - response =self.dew_client.kms_client.update_key_description(request) + response = self.dew_client.kms_client.update_key_description(request) self.logger.info("Successfully update_key_description:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def cancel_key_deletion(self,key_id=None,sequence=None, **kwargs): + def cancel_key_deletion(self, key_id = None, sequence = None, **kwargs): + """ + Cancel plan to delete key. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + """ try: request = CancelKeyDeletionRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.cancel_key_deletion(request) self.logger.info("Successfully canccel key daletion:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_data_key(self,key_id,key_spec=None, datakey_length=None, sequence=None, **kwargs): + def create_data_key(self, key_id, key_spec = None, datakey_length = None, sequence = None, **kwargs): + """ + Create a data key and return a result containing both plaintext and ciphertext. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + """ try: request = CreateDatakeyRequest() request.body = CreateDatakeyRequestBody( - key_id=key_id, - key_spec=key_spec, - datakey_length=datakey_length, - sequence=sequence + key_id = key_id, + key_spec = key_spec, + datakey_length = datakey_length, + sequence = sequence ) response = self.dew_client.kms_client.create_datakey(request) self.logger.info("Successfully created datakey:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_data_key_without_plaintext(self,key_id,key_spec=None, datakey_length=None, sequence=None, **kwargs): + def create_data_key_without_plaintext(self, key_id, key_spec = None, datakey_length = None, sequence = None, **kwargs): + """ + Create a data key and return a result that only contains ciphertext. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + """ try: request = CreateDatakeyWithoutPlaintextRequest() request.body = CreateDatakeyRequestBody( - key_id=key_id, - key_spec=key_spec, - datakey_length=datakey_length, - sequence=sequence + key_id = key_id, + key_spec = key_spec, + datakey_length = datakey_length, + sequence = sequence ) response = self.dew_client.kms_client.create_datakey_without_plaintext(request) self.logger.info("Successfully created datakey without plaintext:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_random(self,random_data_length=None, sequence=None, **kwargs): + def create_random(self, random_data_length = None, sequence = None, **kwargs): + """ + Generate random numbers within the range of 8-8192 bits. + + Args: + :param random_ Data_ Length: The bit length of a random number. The value is a multiple of 8, with a range of 8 to 8192. + The bit length of a random number, with a value of 512. + :type random_ Data_ Length: str + """ try: request = CreateRandomRequest() request.body = GenRandomRequestBody( - random_data_length=random_data_length, - sequence=sequence + random_data_length = random_data_length, + sequence = sequence ) response = self.dew_client.kms_client.create_random(request) self.logger.info("Successfully created random:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def decrypt_data_key(self,key_id=None, cipher_text=None, datakey_cipher_length=None, sequence=None, **kwargs): + def decrypt_data_key(self, key_id = None, cipher_text = None, datakey_cipher_length = None, sequence = None, **kwargs): + """ + Decrypt data key, decrypt data key with specified master key. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + + :cipher_text: The hexadecimal string of DEK ciphertext and metadata. + The value is the cipher in the encrypted data key result_ The value of text. + :type cipher_text: str + + :datakey_cipher_length: The key byte length, with a range of 1 to 1024. Key byte length, with a value of "64". + :type datakey_cipher_length: str + """ try: request = DecryptDatakeyRequest() request.body = DecryptDatakeyRequestBody( - key_id=key_id, - cipher_text=cipher_text, - datakey_cipher_length=datakey_cipher_length, - sequence=sequence + key_id = key_id, + cipher_text = cipher_text, + datakey_cipher_length = datakey_cipher_length, + sequence = sequence ) response = self.dew_client.kms_client.decrypt_datakey(request) self.logger.info("Successfully decrypted datakey:") @@ -245,295 +356,481 @@ class DewBlock(Block): return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def encrypt_data_key(self,key_id=None, plain_text=None, datakey_plain_length=None, sequence=None, **kwargs): + def encrypt_data_key(self, key_id = None, plain_text = None, datakey_plain_length = None, sequence = None, **kwargs): + """ + Encrypt the data key with the specified master key. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + + :param plain_ Text: When CMK is AES, SHA256 (32 bytes) for DEK plaintext and DEK plaintext; When CMK is SM4, + both DEK plaintext and SM3 (32 bytes) of DEK plaintext are represented as hexadecimal strings. + :type plain_ Text: str + + :param datakey_ Plain_ Length: DEK plaintext byte length, with a range of 1 to 1024. DEK plaintext byte length, with a value of "64". + :type datakey_ Plain_ Length: str + """ try: request = EncryptDatakeyRequest() request.body = EncryptDatakeyRequestBody( - key_id=key_id, - plain_text=plain_text, - datakey_plain_length=datakey_plain_length, - sequence=sequence + key_id = key_id, + plain_text = plain_text, + datakey_plain_length = datakey_plain_length, + sequence = sequence ) response = self.dew_client.kms_client.encrypt_datakey(request) self.logger.info("Successfully encrypted datakey:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_parameters_for_import(self,key_id,wrapping_algorithm=None, sequence=None, **kwargs): + def create_parameters_for_import(self, key_id,wrapping_algorithm = None, sequence = None, **kwargs): + """ + Obtain the necessary parameters for importing keys, including key import tokens and key encryption public keys. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + :wrapping_algorithm: Key material encryption algorithm, enumeration as follows: - RSAES_ OAEP_ SHA_ 256- SM2_ ENCRYPT, + some offices do not support this import type + :type wrapping_ algorithm: str + """ try: request = CreateParametersForImportRequest() request.body = GetParametersForImportRequestBody( - key_id=key_id, - wrapping_algorithm=wrapping_algorithm, - sequence=sequence + key_id = key_id, + wrapping_algorithm = wrapping_algorithm, + sequence = sequence ) response = self.dew_client.kms_client.create_parameters_for_import(request) self.logger.info("Successfully created parameters for import:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def delete_imported_key_material(self,key_id,sequence=None, **kwargs): + def delete_imported_key_material(self, key_id, sequence = None, **kwargs): + """ + Delete key material information. + + Args: + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_ Id: str + """ try: request = DeleteImportedKeyMaterialRequest() request.body = OperateKeyRequestBody( key_id = key_id, - sequence=sequence + sequence = sequence ) response = self.dew_client.kms_client.delete_imported_key_material(request) self.logger.info("Successfully deleted imported key material:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def import_key_material(self,key_id=None, import_token=None, - encrypted_key_material=None, encrypted_privatekey=None, - expiration_time=None, sequence=None, **kwargs): + def import_key_material(self, key_id = None, import_token = None, + encrypted_key_material = None, encrypted_privatekey = None, + expiration_time = None, sequence = None, **kwargs): + """ + Import key materials. + + Args: + : param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param import_token: Key import token, in base64 format, that satisfies regular matching "^[0-9a-zA-Z+/=]{200,6144}$". + :type import_ Token: str + + :param encrypted_key_material: The encrypted symmetric key material, in base64 format, satisfies regular matching + "^[0-9a-zA-Z+/=]{344,360}$". If importing an asymmetric key, this parameter is the temporary intermediate key used to encrypt the private key. + :type encrypted_key_material: str + """ try: request = ImportKeyMaterialRequest() request.body = ImportKeyMaterialRequestBody( - key_id=key_id, - import_token=import_token, - encrypted_key_material=encrypted_key_material, - encrypted_privatekey=encrypted_privatekey, - expiration_time=expiration_time, - sequence=sequence + key_id = key_id, + import_token = import_token, + encrypted_key_material = encrypted_key_material, + encrypted_privatekey = encrypted_privatekey, + expiration_time = expiration_time, + sequence = sequence ) response = self.dew_client.kms_client.import_key_material(request) self.logger.info("Successfully imported key material:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_grant(self,key_id=None, grantee_principal=None, listOperationsbody=None, - name=None, retiring_principal=None, grantee_principal_type=None, sequence=None, **kwargs): + def create_grant(self, key_id = None, grantee_principal = None, listOperationsbody = None, + name = None, retiring_principal = None, grantee_principal_type = None, sequence = None, **kwargs): + """ + Create authorization, authorized users can operate on the authorization key. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param grantee_principal:Authorized user ID, 1~64 bytes, satisfies regular matching "^[a-zA-Z0-9]{1,64}$". + For example:0d0466b00d0466b00d0466b00d0466b0 + :type grantee_principal: str + + :param operations: List of authorized and allowed operations. Valid values: "create datakey", "create datakey without plaintext", + "encrypt datakey", "decrypt datakey", "describe key", "create grant", "retain grant", "encrypt data", "decrypt data". The valid + values cannot be just "create grant"- "Create datakey" Create data key - "Create datakey without plaintext" Create data key without + plaintext - "encrypt datakey" Encrypt data key - "decrypt datakey" Decrypt data key - "describe key" Query key information - + "retain grant" Retirement authorization - "encrypt data" Encrypt data - "decrypt data" Decrypt data + :type operations: list[str] + """ try: request = CreateGrantRequest() request.body = CreateGrantRequestBody( - key_id=key_id, - grantee_principal=grantee_principal, - operations=listOperationsbody, - grantee_principal_type=grantee_principal_type, - retiring_principal=retiring_principal, - name=name, - sequence=sequence + key_id = key_id, + grantee_principal = grantee_principal, + operations = listOperationsbody, + grantee_principal_type = grantee_principal_type, + retiring_principal = retiring_principal, + name = name, + sequence = sequence ) response = self.dew_client.kms_client.create_grant(request) self.logger.info("Successfully create grant:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(e.status_code) - self.logger.error(e.request_id) - self.logger.error(e.error_code) - self.logger.error(e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_retirable_grants(self,limit=None, marker=None, sequence=None, **kwargs): + def list_retirable_grants(self, limit = None, marker = None, sequence = None, **kwargs): + """ + Query the list of authorizations that users can retire from. + """ try: request = ListRetirableGrantsRequest() request.body = ListRetirableGrantsRequestBody( - limit=limit, - marker=marker, - sequence=sequence + limit = limit, + marker = marker, + sequence = sequence ) response = self.dew_client.kms_client.list_retirable_grants(request) self.logger.info("Successfully list retirable grants:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(e.status_code) - self.logger.error(e.request_id) - self.logger.error(e.error_code) - self.logger.error(e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_grants(self,key_id=None, limit=None, marker=None, sequence=None, **kwargs): + def list_grants(self, key_id = None, limit = None, marker = None, sequence = None, **kwargs): + """ + Authorization list for querying keys + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + """ try: request = ListGrantsRequest() request.body = ListGrantsRequestBody( - key_id=key_id, - limit=limit, - marker=marker, - sequence=sequence + key_id = key_id, + limit = limit, + marker = marker, + sequence = sequence ) response = self.dew_client.kms_client.list_grants(request) self.logger.info("Successfully list grants:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(e.status_code) - self.logger.error(e.request_id) - self.logger.error(e.error_code) - self.logger.error(e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def cancel_self_grant(self,key_id=None, grant_id=None, sequence=None, **kwargs): + def cancel_self_grant(self, key_id = None, grant_id = None, sequence = None, **kwargs): + """ + Retirement authorization means that the authorized user no longer has the right to operate the authorization key. + For example, if user A authorizes user B to operate key A/key, and authorizes user C to revoke the authorization, + then users A, B, and C can all retire the authorization. After retiring the authorization, user B can no longer use key A. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param grant_id: Authorization ID, 64 bytes, satisfies regular matching "^[A-Fa-f0-9]{64}$". + For example:7c9a3286af4fcca5f0a385ad13e1d21a50e27b6dbcab50f37f30f93b8939827d + :type grant_id: str + """ try: request = CancelSelfGrantRequest() request.body = RevokeGrantRequestBody( - grant_id=grant_id, - key_id=key_id, - sequence=sequence + grant_id = grant_id, + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.cancel_self_grant(request) self.logger.info("Successfully cancel self grant:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(e.status_code) - self.logger.error(e.request_id) - self.logger.error(e.error_code) - self.logger.error(e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def cancel_grant(self,key_id=None, grant_id=None, sequence=None, **kwargs): + def cancel_grant(self, key_id = None, grant_id = None, sequence = None, **kwargs): + """ + Revoke authorization, authorize the user to revoke the authorized user's permission to operate the key + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param grant_id: Authorization ID, 64 bytes, satisfies regular matching "^[A-Fa-f0-9]{64}$". + For example:7c9a3286af4fcca5f0a385ad13e1d21a50e27b6dbcab50f37f30f93b8939827d + :type grant_id: str + """ try: request = CancelGrantRequest() request.body = RevokeGrantRequestBody( - grant_id=grant_id, - key_id=key_id, - sequence=sequence + grant_id = grant_id, + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.cancel_grant(request) self.logger.info("Successfully cancel grant:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(e.status_code) - self.logger.error(e.request_id) - self.logger.error(e.error_code) - self.logger.error(e.error_msg) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def decrypt_data(self, cipher_text = None, encryption_algorithm = None, key_id = None, sequence = None, **kwargs): + """ + Decrypting data. + + Args: + :param cipher_text: Encrypted data ciphertext. The value is the cipher in the encrypted data result. + The value of text satisfies regular matching "^[0-9a-zA-Z+/=]{128,5648}$". + :type cipher_text: str - def decrypt_data(self,cipher_text=None, encryption_algorithm=None, key_id=None, sequence=None, **kwargs): + """ try: request = DecryptDataRequest() request.body = DecryptDataRequestBody( - cipher_text=cipher_text, - encryption_algorithm=encryption_algorithm, - key_id=key_id, - sequence=sequence + cipher_text = cipher_text, + encryption_algorithm = encryption_algorithm, + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.decrypt_data(request) self.logger.info("Successfully decrypted data:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def encrypt_data(self,key_id=None,plain_text=None, encryption_algorithm=None, sequence=None, **kwargs): + def encrypt_data(self, key_id = None,plain_text = None, encryption_algorithm = None, sequence = None, **kwargs): + """ + Encrypt data using the specified user master key. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param plain_text: Clear text data, 1-4096 bytes, satisfies regular matching + "^.{14096}$", and the length range after converting to a byte array is 1-4096 bytes.. + :type plain_text: str + """ try: request = EncryptDataRequest() request.body = EncryptDataRequestBody( - plain_text=plain_text, - key_id=key_id, - encryption_algorithm=encryption_algorithm, - sequence=sequence + plain_text = plain_text, + key_id = key_id, + encryption_algorithm = encryption_algorithm, + sequence = sequence ) response = self.dew_client.kms_client.encrypt_data(request) self.logger.info("Successfully encrypted data:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def sign(self,key_id=None, message=None, signing_algorithm=None, message_type=None, sequence=None, **kwargs): + def sign(self, asymmetric_key_id = None, message = None, signing_algorithm = None, message_type = None, sequence = None, **kwargs): + """ + Digitally sign a message or message digest using a private key with an asymmetric key. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param signing_algorithm: The signature algorithm is listed as follows: + - RSASSA_PSS_SHA_256 - RSASSA_PSS_SHA_384 - RSASSA_PSS_SHA_512 - RSASSA_PKCS1_V1_5_SHA_256 + - RSASSA_PKCS1_V1_5_SHA_384 - RSASSA_PKCS1_V1_5_SHA_512 - ECDSA_SHA_256 - ECDSA_SHA_384 + - ECDSA_SHA_512 - SM2DSA_SM3 + :type signing_algorithm: str + + :param message: The message digest or message to be signed must have a message length of less than 4096 bytes and be encoded using Base64. + :type message: str + """ try: request = SignRequest() request.body = SignRequestBody( - signing_algorithm=signing_algorithm, - message=message, - key_id=key_id, - message_type=message_type, - sequence=sequence + signing_algorithm = signing_algorithm, + message = message, + key_id = asymmetric_key_id, + message_type = message_type, + sequence = sequence ) response = self.dew_client.kms_client.sign(request) self.logger.info("Successfully sign:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def validate_signature(self, asymmetric_key_id = None, message = None, signature = None, signing_algorithm = None, + message_type = None, sequence = None, **kwargs): + """ + Verify the signature of a message or message digest using a public key with an asymmetric key. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str - def validate_signature(self, key_id=None, message=None, signature=None, signing_algorithm=None, - message_type=None, sequence=None, **kwargs): + :param signing_algorithm: The signature algorithm is listed as follows: + - RSASSA_PSS_SHA_256 - RSASSA_PSS_SHA_384 - RSASSA_PSS_SHA_512 - RSASSA_PKCS1_V1_5_SHA_256 + - RSASSA_PKCS1_V1_5_SHA_384 - RSASSA_PKCS1_V1_5_SHA_512 - ECDSA_SHA_256 - ECDSA_SHA_384 + - ECDSA_SHA_512 - SM2DSA_SM3 + :type signing_algorithm: str + + :param message: The message digest or message to be signed must have a message length of less than 4096 bytes and be encoded using Base64. + :type message: str + + :param signature: The signature value to be verified is encoded using Base64. + :type signature: str + """ try: request = ValidateSignatureRequest() request.body = VerifyRequestBody( - key_id=key_id, - message=message, - signature=signature, - signing_algorithm=signing_algorithm, - message_type=message_type, - sequence=sequence + key_id = asymmetric_key_id, + message = message, + signature = signature, + signing_algorithm = signing_algorithm, + message_type = message_type, + sequence = sequence ) response = self.dew_client.kms_client.validate_signature(request) self.logger.info("Successfully list validate signature:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_key_detail(self,key_id=None,sequence=None, **kwargs): + def list_key_detail(self, key_id = None,sequence = None, **kwargs): + """ + Query key details. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + """ try: request = ListKeyDetailRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.list_key_detail(request) self.logger.info("Successfully list key detail:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_keys(self,limit=None, marker=None, key_state=None, key_spec=None, - enterprise_project_id=None, sequence=None, **kwargs): + def list_keys(self,limit = None, marker = None, key_state = None, key_spec = None, + enterprise_project_id = None, sequence = None, **kwargs): + """ + Query the list of all user keys. + """ try: request = ListKeysRequest() request.body = ListKeysRequestBody( - limit=limit, - marker=marker, - key_state=key_state, - key_spec=key_spec, - enterprise_project_id=enterprise_project_id, - sequence=sequence + limit = limit, + marker = marker, + key_state = key_state, + key_spec = key_spec, + enterprise_project_id = enterprise_project_id, + sequence = sequence ) response = self.dew_client.kms_client.list_keys(request) self.logger.info(json.dumps(response.to_dict()).replace('}','}\n')) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_public_key(self,key_id=None, sequence=None, **kwargs): + def show_public_key(self, asymmetric_key_id = None, sequence = None, **kwargs): + """ + Query public key information for user specified asymmetric keys. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + """ try: request = ShowPublicKeyRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = asymmetric_key_id, + sequence = sequence ) response = self.dew_client.kms_client.show_public_key(request) self.logger.info("Successfully show public key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") def show_user_instances(self, **kwargs): + """ + Query the number of instances to obtain the number of user master keys that have already been created by the user + """ try: request = ShowUserInstancesRequest() response = self.dew_client.kms_client.show_user_instances(request) @@ -541,10 +838,13 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") def show_user_quotas(self, **kwargs): + """ + Query quotas, query the total number of user master key quotas that users can create and current usage information. + """ try: request = ShowUserQuotasRequest() response = self.dew_client.kms_client.show_user_quotas(request) @@ -552,21 +852,31 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_version(self, **kwargs): + def show_version(self,version_id = None, **kwargs): + """ + Check the specified API version information + + Args: + :param version_id: API version number + :type version_id: str + """ try: - request = ShowVersionRequest(kwargs) + request = ShowVersionRequest(version_id = version_id) response = self.dew_client.kms_client.show_version(request) self.logger.info("Successfully show_version:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") def show_versions(self, **kwargs): + """ + Query API version information list. + """ try: request = ShowVersionsRequest() response = self.dew_client.kms_client.show_versions(request) @@ -576,147 +886,235 @@ class DewBlock(Block): except exceptions.ClientRequestException as e: self.logger.error(e) - def disable_key_rotation(self, key_id=None, sequence=None, **kwargs): + def disable_key_rotation(self, key_id = None, sequence = None, **kwargs): + """ + Turn off user master key rotation. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + """ try: request = DisableKeyRotationRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.disable_key_rotation(request) self.logger.info("Successfully disable key rotation:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def enable_key_rotation(self, key_id=None, sequence=None, **kwargs): + def enable_key_rotation(self, key_id = None, sequence = None, **kwargs): + """ + Enable user master key rotation. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + """ try: request = EnableKeyRotationRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.enable_key_rotation(request) self.logger.info("Successfully enable key rotation:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_key_rotation_status(self, key_id=None, sequence=None, **kwargs): + def show_key_rotation_status(self, key_id = None, sequence = None, **kwargs): + """ + Query user master key rotation status + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + """ try: request = ShowKeyRotationStatusRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.show_key_rotation_status(request) self.logger.info("Successfully show key rotation status:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def update_key_rotation_interval(self, key_id=None, rotation_interval=None, sequence=None, **kwargs): + def update_key_rotation_interval(self, key_id = None, rotation_interval = None, sequence = None, **kwargs): + """ + Modify the user master key rotation cycle. + + Args: + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. + :type key_id: str + + :param rotation_interval: Rotation period, an integer with a range of values from 30 to 365. + The cycle range is set based on the frequency of key usage. If the frequency of key usage is high, + it is recommended to set it to a short cycle; On the contrary, set it to long cycle. + :type rotation_interval: int + """ try: request = UpdateKeyRotationIntervalRequest() request.body = UpdateKeyRotationIntervalRequestBody( - rotation_interval=rotation_interval, - key_id=key_id, - sequence=sequence + rotation_interval = rotation_interval, + key_id = key_id, + sequence = sequence ) response = self.dew_client.kms_client.update_key_rotation_interval(request) self.logger.info("Successfully update key rotation interval:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def create_keypair(self,name = None, type = None, public_key = None, scope = None, user_id = None, key_protection = None, **kwargs): + """ + Create and import SSH key pairs. - def create_keypair(self,name=None, type=None, public_key=None, scope=None, user_id=None, key_protection=None, **kwargs): + Args: + :param name: The name of the SSH key pair.-The name of a newly created key pair cannot be the same as the name of an existing key pair. + - The SSH key pair name consists of English letters, numbers, underscores, and midlines, and the length cannot exceed 64 bytes + :type name: str + """ try: request = CreateKeypairRequest() key_pair_body = CreateKeypairAction( - name=name, - type=type, - public_key=public_key, - scope=scope, - user_id=user_id, - key_protection=key_protection + name = name, + type = type, + public_key = public_key, + scope = scope, + user_id = user_id, + key_protection = key_protection ) request.body = CreateKeypairRequestBody( - keypair=key_pair_body + keypair = key_pair_body ) response = self.dew_client.kps_client.create_keypair(request) self.logger.info("Successfully created keypair:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_keypairs(self,limit=None, marker=None, **kwargs): + def list_keypairs(self,limit = None, marker = None, **kwargs): + """ + Query SSH key pair list. + """ try: - request = ListKeypairsRequest(limit=limit, marker=marker) + request = ListKeypairsRequest(limit = limit, marker = marker) response = self.dew_client.kps_client.list_keypairs(request) self.logger.info("Successfully list keypairs:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def clear_private_key(self, keypair_name=None, **kwargs): + def clear_private_key(self, keypair_name = None, **kwargs): + """ + Clear SSH key pair private key + + Args: + :param keypair_name: Key pair name. + :type keypair_name: str + """ try: - request = ClearPrivateKeyRequest(keypair_name=keypair_name) + request = ClearPrivateKeyRequest(keypair_name = keypair_name) response = self.dew_client.kps_client.clear_private_key(request) self.logger.info("Successfully cleared private key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def import_private_key(self, user_id=None, name=None,type="default", kms_key_name="kps/default", private_key=None, **kwargs): + def import_private_key(self, user_id = None, name = None,type = None, kms_key_name = None, private_key = None, **kwargs): + """ + Import the private key into the specified key pair. + + Args: + :param name: The name of the SSH key pair.- The name of a newly created key pair cannot be the same as the name of an existing key pair. + - The SSH key pair name consists of English letters, numbers, underscores, and midlines, and the length cannot exceed 64 bytes + :type name: str + + :param private_key: Import the private key of an SSH key pair. + :type private_key: str + + :param type: 取值范围: "kms" or "default"- "Default" is the default encryption method, suitable for offices without KMS services. + - "KMS" refers to the use of KMS service encryption method. If the station does not have KMS service, please fill in "default". + :type type: str + + :param kms_key_name: The name of the KMS key.- If "type" is "kms", the kms service key name must be filled in. + :type kms_key_name: str + """ try: request = ImportPrivateKeyRequest() encryption_key_protection = Encryption( - type=type, - kms_key_name=kms_key_name + type = type, + kms_key_name = kms_key_name ) key_protection_keypair = ImportPrivateKeyProtection( - private_key=private_key, - encryption=encryption_key_protection + private_key = private_key, + encryption = encryption_key_protection ) key_pair_body = ImportPrivateKeyKeypairBean( - name=name, - key_protection=key_protection_keypair, - user_id=user_id + name = name, + key_protection = key_protection_keypair, + user_id = user_id ) - request.body = ImportPrivateKeyRequestBody(keypair=key_pair_body) + request.body = ImportPrivateKeyRequestBody(keypair = key_pair_body) response = self.dew_client.kps_client.import_private_key(request) self.logger.info("Successfully import_private_key:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_keypair_detail(self, keypair_name=None, **kwargs): + def list_keypair_detail(self, keypair_name = None, **kwargs): + """ + Query SSH key pair details + + Args: + :param keypair_name: Key pair name. + :type keypair_name: str + """ try: - request = ListKeypairDetailRequest(keypair_name=keypair_name) + request = ListKeypairDetailRequest(keypair_name = keypair_name) response = self.dew_client.kps_client.list_keypair_detail(request) - self.logger.info("Successfully list private key detail:") + self.logger.info("Successfully list_keypair_detail") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_keypairs(self, keypair_name=None, **kwargs): + def list_keypairs(self, **kwargs): + """ + Query SSH key pair list + """ try: request = ListKeypairsRequest() response = self.dew_client.kps_client.list_keypairs(request) @@ -724,139 +1122,230 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def update_keypair_description(self, keypair_name=None, description=None, **kwargs): + def update_keypair_description(self, keypair_name = None, description = None, **kwargs): + """ + Update SSH key pair description. + + Args: + :param keypair_name: Key pair name. + :type keypair_name: str + + :param description: Descriptive information + :type description: str + """ try: request = UpdateKeypairDescriptionRequest( - keypair_name=keypair_name + keypair_name = keypair_name ) key_pair_body = UpdateKeypairDescriptionReq( - description=description + description = description ) request.body = UpdateKeypairDescriptionRequestBody( - keypair=key_pair_body + keypair = key_pair_body ) response = self.dew_client.kps_client.update_keypair_description(request) - self.logger.info("Successfully updated:") + self.logger.info("Successfully update keypair description:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def export_private_key(self, name=None, **kwargs): + def export_private_key(self, name = None, **kwargs): + """ + Export the private key of the specified key pair. + + :param name: SSH key pair name. + :type name: str + """ try: request = ExportPrivateKeyRequest() - key_pair_body = KeypairBean(name=name) - request.body = ExportPrivateKeyRequestBody(keypair=key_pair_body) + key_pair_body = KeypairBean(name = name) + request.body = ExportPrivateKeyRequestBody(keypair = key_pair_body) response = self.dew_client.kps_client.export_private_key(request) self.logger.info("Successfully exported private key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def delete_keypair(self,keypair_name=None, **kwargs): + def delete_keypair(self, keypair_name = None, **kwargs): + """ + Delete SSH key pair. + + Args: + :param keypair_name: Key pair name. + :type keypair_name: str + """ try: - request = DeleteKeypairRequest(keypair_name=keypair_name) + request = DeleteKeypairRequest(keypair_name = keypair_name) response = self.dew_client.kps_client.delete_keypair(request) self.logger.info("Successfully deleted keypair") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def associate_keypair(self, keypair_name = None,type = None, key = None,id = None, disable_password = False, port = None, **kwargs): + """ + Bind a new SSH key pair to the specified virtual machine (replace or reset, replacement requires providing + the configured SSH key pair private key of the virtual machine; reset does not require providing the SSH key + pair private key of the virtual machine). + + Args: + :param keypair_name: Key pair name. + :type keypair_name: str + + :param id: Virtual machine id that needs to bind (replace or reset) SSH key pairs. + :type id: str - def associate_keypair(self,keypair_name=None,type=None,key=None,id=None, disable_password=False, port=None, **kwargs): + :param type: The value is of enumeration type. password or keypair. + :type type: str + + :param key: - When type is the enumeration value password, key represents the password- When type is the enumeration + value keypair, key represents the private key. + :type key: str + """ try: request = AssociateKeypairRequest() - auth_server = Auth(type=type, key=key) + auth_server = Auth(type = type, key = key) server_body = EcsServerInfo( - id=id, - auth=auth_server, - disable_password=disable_password, - port=port + id = id, + auth = auth_server, + disable_password = disable_password, + port = port ) request.body = AssociateKeypairRequestBody( - server=server_body, - keypair_name=keypair_name + server = server_body, + keypair_name = keypair_name ) response = self.dew_client.kps_client.associate_keypair(request) self.logger.info("Successfully associate_keypair:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.info(id) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def batch_associate_keypair(self, keypair_name=None, type=None, key=None, id=None, disable_password=None, port=None, **kwargs): + def batch_associate_keypair(self, keypair_name = None, type = None, key = None, id = None, disable_password = None, port = None, **kwargs): + """ + Batch bind new SSH key pairs to the specified virtual machine. + + Args: + :param keypair_name: The name of the SSH key pair + :type keypair_name: list[str] + + :param id: List of virtual machine IDs that require binding (replacing or resetting) SSH key pairs. + :type id: list[str] + """ try: request = BatchAssociateKeypairRequest() list_batch_keypairs_body = [] - for s in range(len(keypair_name), **kwargs): + if isinstance(keypair_name,list): + for s in range(len(keypair_name)): + auth_server = Auth( + type = type[s] if type is not None else None, + key = key[s] if key is not None else None + ) + server_satch_keypairs = EcsServerInfo( + id = id[s] if id is not None else None, + auth = auth_server, + disable_password = disable_password[s] if disable_password is not None else None, + port = port[s] if port is not None else None + ) + list_batch_keypairs_body.append(AssociateKeypairRequestBody( + keypair_name = keypair_name[s] if keypair_name is not None else None, + server = server_satch_keypairs + )) + else: auth_server = Auth( - type=type[s], - key=key[s] - ) + type = type, + key = key + ) server_satch_keypairs = EcsServerInfo( - id=id[s], - auth=auth_server, - disable_password=disable_password[s], - port=port[s] + id = id, + auth = auth_server, + disable_password = disable_password, + port = port ) list_batch_keypairs_body.append(AssociateKeypairRequestBody( - keypair_name=keypair_name[s], - server=server_satch_keypairs + keypair_name = keypair_name, + server = server_satch_keypairs )) - + request.body = BatchAssociateKeypairRequestBody( - batch_keypairs=list_batch_keypairs_body + batch_keypairs = list_batch_keypairs_body ) response = self.dew_client.kps_client.batch_associate_keypair(request) self.logger.info("Successfully batch_associate_keypair:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") def delete_all_failed_task(self, **kwargs): + """ + Delete task information that failed the operation. + """ try: request = DeleteAllFailedTaskRequest() response = self.dew_client.kps_client.delete_all_failed_task(request) self.logger.info("Successfully delete_all_failed_task:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") def delete_failed_task(self, task_id, **kwargs): + """ + Delete failed tasks. + + :param task_id: Task ID + :type task_id: str + """ try: request = DeleteFailedTaskRequest( - task_id=task_id, + task_id = task_id, ) response = self.dew_client.kps_client.delete_failed_task(request) self.logger.info("Successfully delete_failed_task:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def disassociate_keypair(self, id=None, type=None, key=None, **kwargs): + def disassociate_keypair(self, id = None, type = None, key = None, **kwargs): + """ + Unbind SSH key pairs to the specified virtual machine and restore SSH password login. + :param id: Virtual machine ID that needs to bind (replace or reset) SSH key pairs + :type id: str + """ try: request = DisassociateKeypairRequest() - auth_server = Auth(type=type, key=key) - server_body = DisassociateEcsServerInfo(id=id, auth=auth_server) - request.body = DisassociateKeypairRequestBody(server=server_body) + auth_server = Auth(type = type, key = key) + server_body = DisassociateEcsServerInfo(id = id, auth = auth_server) + request.body = DisassociateKeypairRequestBody(server = server_body) response = self.dew_client.kps_client.disassociate_keypair(request) self.logger.info("Successfully disassociate_keypair:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_failed_task(self, limit=None, offset=None, **kwargs): + def list_failed_task(self, limit = None, offset = None, **kwargs): + """ + Query task information for failed binding, unbinding, and other operations. + """ try: request = ListFailedTaskRequest() request.limit = limit @@ -864,21 +1353,33 @@ class DewBlock(Block): response = self.dew_client.kps_client.list_failed_task(request) self.logger.info("Successfully list_failed_task:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_keypair_task(self, task_id=None, **kwargs): + def list_keypair_task(self, task_id = None, **kwargs): + """ + The task returned by the interface based on the SSH key_ ID, query the execution status of the SSH key for the current task. + + Args: + :param task_id: task ID + :type task_id: str + """ try: - request = ListKeypairTaskRequest(task_id=task_id) + request = ListKeypairTaskRequest(task_id = task_id) response = self.dew_client.kps_client.list_keypair_task(request) self.logger.info("Successfully list_keypair_task:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_running_task(self, limit=None, offset=None, **kwargs): + def list_running_task(self, limit = None, offset = None, **kwargs): + """ + Query the task information being processed. + """ try: request = ListRunningTaskRequest() request.limit = limit @@ -886,47 +1387,73 @@ class DewBlock(Block): response = self.dew_client.kps_client.list_running_task(request) self.logger.info("Successfully list_running_task:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_secret(self, name=None, kms_key_id=None, description=None, - secret_binary=None, secret_string=None, secret_type=None, - auto_rotation=None, rotation_period=None, rotation_config=None, - event_subscriptions=None, enterprise_project_id=None, **kwargs): + def create_secret(self, name = None, kms_key_id = None, description = None, + secret_binary = None, secret_string = None, secret_type = None, + auto_rotation = None, rotation_period = None, rotation_config = None, + event_subscriptions = None, enterprise_project_id = None, **kwargs): + """ + Create a new credential and store the credential value in the initial version of the credential. + The credential management service encrypts the credential values and stores them in the version under the credential object. + Each version can be associated with multiple credential version states, which are used to identify the stage in which the credential + version is in. A version without a version state marker is considered deprecated and can be automatically deleted using the credential + management service. + The initial version status is marked as SYSCURRENT. + + Args: + :param name: The name of the credential to be created. Constraint: The value range is 1 to 64 characters, satisfying the regular matching + "^[a-zA-Z0-9_-]{1,64}$". + :type name: str + """ try: request = CreateSecretRequest() request.body = CreateSecretRequestBody( - secret_string=secret_string, - kms_key_id=kms_key_id, - name=name, - description=description, - secret_binary=secret_binary, - secret_type=secret_type, - auto_rotation=auto_rotation, - rotation_period=rotation_period, - rotation_config=rotation_config, - event_subscriptions=event_subscriptions, - enterprise_project_id=enterprise_project_id + secret_string = secret_string, + kms_key_id = kms_key_id, + name = name, + description = description, + secret_binary = secret_binary, + secret_type = secret_type, + auto_rotation = auto_rotation, + rotation_period = rotation_period, + rotation_config = rotation_config, + event_subscriptions = event_subscriptions, + enterprise_project_id = enterprise_project_id ) response = self.dew_client.cms_client.create_secret(request) self.logger.info("Successfully create_secret:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def download_secret_blob(self, secret_name=None, **kwargs): + def download_secret_blob(self, secret_name = None, **kwargs): + """ + Download backup files for specified credentials. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: - request = DownloadSecretBlobRequest(secret_name=secret_name) + request = DownloadSecretBlobRequest(secret_name = secret_name) response = self.dew_client.cms_client.download_secret_blob(request) self.logger.info("Successfully download_secret_blob:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_secrets(self, limit=None, marker=None, event_name=None, **kwargs): + def list_secrets(self, limit = None, marker = None, event_name = None, **kwargs): + """ + Query all credentials created by the current user under this project. + """ try: request = ListSecretsRequest() request.limit = limit @@ -935,137 +1462,246 @@ class DewBlock(Block): response = self.dew_client.cms_client.list_secrets(request) self.logger.info("Successfully list_secrets:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") def show_secret(self, secret_name, **kwargs): + """ + Query information for specified credentials. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: - request = ShowSecretRequest(secret_name=secret_name) + request = ShowSecretRequest(secret_name = secret_name) response = self.dew_client.cms_client.show_secret(request) self.logger.info("Successfully show_secret:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def update_secret(self, kms_key_id=None, secret_name=None, description=None, - auto_rotation=None, rotation_period=None, listEventSubscriptionsbody=None, **kwargs): + def update_secret(self, kms_key_id = None, secret_name = None, description = None, + auto_rotation = None, rotation_period = None, listEventSubscriptionsbody = None, **kwargs): + """ + Update metadata information for specified credentials. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: request = UpdateSecretRequest() request.body = UpdateSecretRequestBody( - event_subscriptions=listEventSubscriptionsbody, - description=description, - kms_key_id=kms_key_id, - auto_rotation=auto_rotation, - rotation_period=rotation_period, + event_subscriptions = listEventSubscriptionsbody, + description = description, + kms_key_id = kms_key_id, + auto_rotation = auto_rotation, + rotation_period = rotation_period, ) - request.secret_name=secret_name + request.secret_name = secret_name response = self.dew_client.cms_client.update_secret(request) self.logger.info("Successfully update_secret:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_secret_event(self, target_type=None, target_id=None, - target_name=None, name=None, state=None, - listEventTypesbody=None, **kwargs): + def create_secret_event(self, target_type = None, target_id = None, + target_name = None, event_name = None, state = None, + event_types = None, **kwargs): + """ + Create an event that can be configured on one or more credential objects. When an event is enabled and the + underlying event type is triggered on the credential object, the cloud service will send the corresponding + event notification to the notification subject specified by the event. + + Args: + :param name: The name of the newly created event notification. Constraint: The value range is 1 to 64 + characters, satisfying the regular matching "^ [a-zA-Z0-9_ -] {1,64} $". + :type name: str + + :param event_types:he basic event list for this event notification, with the following basic event types. + SECRET_ VERSION_ CREATED: Version Creation SECRET_ VERSION_ EXPIRED: Version expired SECRET_ ROTATED: credential + rotation SECRET_ DELETED: The credential deletion list cannot contain duplicate underlying event types. + :type event_types: list[str] + + :param state: controls whether an event takes effect. Only the enabled state can trigger the underlying event types + included.ENABLED: enable DisaBLED: disable + :type state: str + + :param target_ Type: The object type of the event notification. + :type target_ Type: str + + :param target_ ID: The object ID of the event notification. + :type target_ Id: str + + :param target_ Name: The name of the object notified by the event. + :type target_ Name: str + """ try: request = CreateSecretEventRequest() notification_body = Notification( - target_type=target_type, - target_id=target_id, - target_name=target_name + target_type = target_type, + target_id = target_id, + target_name = target_name ) request.body = CreateSecretEventRequestBody( - notification=notification_body, - state=state, - event_types=listEventTypesbody, - name=name, + notification = notification_body, + state = state, + event_types = event_types, + name = event_name, ) response = self.dew_client.cms_client.create_secret_event(request) self.logger.info("Successfully create_secret_event:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def upload_secret_blob(self, secret_blob, **kwargs): + def upload_secret_blob(self, secret_blob=None, **kwargs): + """ + Restore credential objects by uploading credential backup files. + + Args: + :param secret_blob: The credential backup file obtained by backing up the specified credential object contains + all current credential version information. The backup file is encrypted and encoded, and its content cannot be read directly. + :type secret_blob: str + """ try: request = UploadSecretBlobRequest() - request.body = UploadSecretBlobRequestBody(secret_blob=secret_blob) + request.body = UploadSecretBlobRequestBody(secret_blob = secret_blob) response = self.dew_client.cms_client.upload_secret_blob(request) self.logger.info("Successfully upload_secret_blob:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: self.logger.error(e.status_code) self.logger.error(e.request_id) self.logger.error(e.error_code) - def rotate_secret(self,secret_name=None, **kwargs): + def rotate_secret(self,secret_name = None, **kwargs): + """ + Immediately execute the rotation of credentials. Create a new credential version within the specified credentials to encrypt + and store randomly generated credential values in the background. At the same time, mark the newly created credential version + as SYSCURRENT status. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: - request = RotateSecretRequest(secret_name=secret_name) + request = RotateSecretRequest(secret_name = secret_name) response = self.dew_client.cms_client.rotate_secret(request) self.logger.info("Successfully rotate_secret:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") def restore_secret(self,secret_name, **kwargs): + """ + Cancel the scheduled deletion task of credentials and restore the usable state of the credential object. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: - request = RestoreSecretRequest(secret_name=secret_name) + request = RestoreSecretRequest(secret_name = secret_name) response = self.dew_client.cms_client.restore_secret(request) self.logger.info("Successfully restore_secret:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def delete_secret_for_schedule(self,recovery_window_in_days=None,secret_name=None, **kwargs): + def delete_secret_for_schedule(self,recovery_window_in_days = None,secret_name = None, **kwargs): + """ + Specify a delayed deletion time, create a scheduled task to delete credentials, and set a delayed deletion time of 7-30 days. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + + :param recovery_ Window_ In_ Days: Create a task to delete credentials on a scheduled basis, and specify the number of days + that can be recovered. Constraints: 7-30. Default value: 30. + :type recovery_ Window_ In_ Days: int + """ try: - request = DeleteSecretForScheduleRequest(secret_name=secret_name) + request = DeleteSecretForScheduleRequest(secret_name = secret_name) request.body = DeleteSecretForScheduleRequestBody( - recovery_window_in_days=recovery_window_in_days + recovery_window_in_days = recovery_window_in_days ) response = self.dew_client.cms_client.delete_secret_for_schedule(request) self.logger.info("Successfully delete_secret_for_schedule:") - self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") def delete_secret(self,secret_name, **kwargs): + """ + Immediately delete the specified credentials and cannot recover them. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: - request = DeleteSecretRequest(secret_name=secret_name) + request = DeleteSecretRequest(secret_name = secret_name) response = self.dew_client.cms_client.delete_secret(request) self.logger.info("Successfully delete_secret:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_secret_version(self,secret_name=None,secret_binary=None, - secret_string=None, version_stages=None, expire_time=None, **kwargs): + def create_secret_version(self,secret_name = None,secret_binary = None, + secret_string = None, version_stages = None, expire_time = None, **kwargs): + """ + Create a new credential version within the specified credentials to encrypt and store the new credential values. + By default, newly created credential versions are marked as SYSCURRENT, while the previous credential version marked + with SYSCURRENT is marked as SYSPREVIOUS. You can override the default behavior by specifying the Version Stage parameter. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: request = CreateSecretVersionRequest(secret_name=secret_name) request.body = CreateSecretVersionRequestBody( - secret_string=secret_string, - secret_binary=secret_binary, - version_stages=version_stages, - expire_time=expire_time + secret_string = secret_string, + secret_binary = secret_binary, + version_stages = version_stages, + expire_time = expire_time ) response = self.dew_client.cms_client.create_secret_version(request) self.logger.info("Successfully create_secret_version:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_secret_versions(self,secret_name=None, marker=None, limit=None, **kwargs): + def list_secret_versions(self,secret_name = None, marker = None, limit = None, **kwargs): + """ + Query version list information under specified credentials. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + """ try: request = ListSecretVersionsRequest() request.secret_name = secret_name @@ -1074,35 +1710,565 @@ class DewBlock(Block): response = self.dew_client.cms_client.list_secret_versions(request) self.logger.info("Successfully list_secret_versions:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_secret_version(self,secret_name=None,version_id=None, **kwargs): + def show_secret_version(self,secret_name = None,version_id = None, **kwargs): + """ + Query the information of the specified credential version and the plaintext credential value in the version, + only the credentials with ENABLED status can be queried. The latest version of the credentials can be accessed + through/v1/{project_id}/secrets/{secretname}/versions/latest (i.e. assigning {version _id} in the current interface URL as latest) + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + + :param version_id: The version identifier of the credential. + :type version_id: str + """ try: request = ShowSecretVersionRequest() - request.secret_name=secret_name + request.secret_name = secret_name request.version_id = version_id response = self.dew_client.cms_client.show_secret_version(request) self.logger.info("Successfully show_secret_version:") self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") - def update_version(self,secret_name=None, version_id=None, expire_time=None, **kwargs): + def update_version(self,secret_name = None, version_id = None, expire_time = None, **kwargs): + """ + Currently, it supports updating the validity period of specified credential versions, and can only update + credentials with ENABLED status. When the event associated with the subscription includes a basic event type + of "version expiration", only one event notification will be triggered after each version expiration update. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + + :param version_id: The version identifier of the credential. + :type version_id: str + + :param expire_time: The expiration time of the credential version, timestamp, is the total number of seconds + from January 1, 1970 to that time. The default is empty, and the value used to determine the validity period + when subscribing to the "version expiration" event type for credentials. + :type expire_time: int + """ try: request = UpdateVersionRequest() - request.version_id=version_id - request.secret_name=secret_name + request.version_id = version_id + request.secret_name = secret_name request.body = UpdateVersionRequestBody( - expire_time=expire_time + expire_time = expire_time ) response = self.dew_client.cms_client.update_version(request) self.logger.info("Successfully update_version:") self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def show_secret_stage(self, secret_name=None, stage_name=None, **kwargs): + """ + Query the version information of the specified credential version status marker. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + + :param stage_name: The name of the credential version status. + :type stage_name: str + """ + try: + request = ShowSecretStageRequest(secret_name=secret_name,stage_name=stage_name) + response = self.dew_client.cms_client.show_secret_stage(request) + self.logger.info("Successfully show_secret_stage:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def update_secret_stage(self, secret_name = None, stage_name = None, version_id = None, **kwargs): + """ + Update the version status of credentials. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + + :param stage_name: The name of the credential version status.matching '^[a-zA-Z0-9_-]{1,64}$' + :type stage_name: str + """ + try: + request = UpdateSecretStageRequest(secret_name = secret_name, stage_name = stage_name) + request.body = UpdateSecretStageRequestBody(version_id = version_id) + response = self.dew_client.cms_client.update_secret_stage(request) + self.logger.info("Successfully update_secret_stage:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def delete_secret_stage(self, secret_name = None, stage_name = None, **kwargs): + """ + Delete the version status of credentials. + + Args: + :param secret_name: The name of the credential. + :type secret_name: str + + :param stage_name: The name of the credential version status. + :type stage_name: str + """ + try: + request = DeleteSecretStageRequest(secret_name = secret_name, stage_name = stage_name) + response = self.dew_client.cms_client.delete_secret_stage(request) + self.logger.info("Successfully delete_secret_stage:") + self.logger.info(response) + return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code= {e.status_code}, request_id= {e.request_id},\ - error_code= {e.error_code}, error_msg= {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + def batch_create_or_delete_tags(self, secret_id = None, key = None, value = None, action = None, sequence = None, **kwargs): + """ + Batch add or remove credential labels. + + Args: + :param secret_id: Credential ID + :type secret_id: str + :param key: The name of the tag. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + The value range is from 1 to 128 characters, which satisfies regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L} + \\\\p{Z}\\\\p{N}_.:=+\\\\-@]*)(?<!\\\\s)$\" + :type key: list[str] + + :param action: Operation identifier: limited to "create" and "delete" only. + :type action: str + """ + try: + request = BatchCreateOrDeleteTagsRequest(secret_id = secret_id) + + + listTagsbody = [] + if isinstance(key,list): + for s in range(len(key)): + listTagsbody.append(TagItem(key =key[s], + value = value[s] if value is not None else None)) + else: + listTagsbody.append(TagItem(key =key, value = value)) + + request.body = BatchCreateOrDeleteTagsRequestBody( + action=action, + tags=listTagsbody, + sequence=sequence + ) + response = self.dew_client.cms_client.batch_create_or_delete_tags(request) + self.logger.info("Successfully batch_create_or_delete_tags:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def create_secret_tag(self, secret_id = None, key = None, value = None, **kwargs): + """ + Add credential labels. + + Args: + :param secret_id: Credential ID + :type secret_id: str + + :param key: The name of the tag. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + The value range is from 1 to 128 characters, which satisfies regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L} + \\\\p{Z}\\\\p{N}_.:=+\\\\-@]*)(?<!\\\\s)$\" + :type key: str + """ + try: + request = CreateSecretTagRequest(secret_id = secret_id) + tagbody = TagItem( + key = key, + value = value, + ) + request.body = CreateSecretTagRequestBody( + tag=tagbody + ) + response = self.dew_client.cms_client.create_secret_tag(request) + self.logger.info("Successfully create_secret_tag:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def delete_secret_tag(self, secret_id = None, key = None, **kwargs): + """ + Delete credential labels. + + Args: + :param secret_id: Credential ID + :type secret_id: str + + :param key: The name of the tag. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + The value range is from 1 to 128 characters, which satisfies regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L} + \\\\p{Z}\\\\p{N}_.:=+\\\\-@]*)(?<!\\\\s)$\" + :type key: str + """ + try: + request = DeleteSecretTagRequest(secret_id = secret_id, key = key) + response = self.dew_client.cms_client.delete_secret_tag(request) + self.logger.info("Successfully delete_secret_tag:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def list_project_secrets_tags(self,**kwargs): + """ + Query the collection of all credential labels for the user under the specified project. + """ + try: + request = ListProjectSecretsTagsRequest() + response = self.dew_client.cms_client.list_project_secrets_tags(request) + self.logger.info("Successfully list_project_secrets_tags:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def list_resource_instances(self,resource_instances = None, values = None, key = None, limit = None, offset=None, action = None, matches = None, sequence = None, **kwargs): + """ + Query credential instances. Filter user credentials through tag filtering and return a list of credentials. + + Args: + :param action: Operation identifier (can be set as "filter" or "count")- Filter: represents filtering + - Count: represents the total number of queries. + :type action: str + + :param resource_instances: Set the value to resource_instances. + :type resource_instances: str + """ + try: + request = ListResourceInstancesRequest(resource_instances = resource_instances) + listTagsbody = [] + if isinstance(key,list): + for s in range(len(key)): + listTagsbody.append(Tag(key = key[s] if key is not None else None, + values = values[s] if values is not None else None)) + else: + listTagsbody.append(Tag(key = key, values = values)) + request.body = ListResourceInstancesRequestBody( + tags = listTagsbody if key is not None else None, + action = action, + matches = matches, + sequence = sequence, + offset = offset, + limit = limit + ) + response = self.dew_client.cms_client.list_resource_instances(request) + self.logger.info("Successfully list_resource_instances:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def list_secret_tags(self, secret_id = None, **kwargs): + """ + Query credential labels. + + Args: + :param secret_id: Credential ID + :type secret_id: str + """ + try: + request = ListSecretTagsRequest(secret_id = secret_id) + response = self.dew_client.cms_client.list_secret_tags(request) + self.logger.info("Successfully list_secret_tags:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def delete_secret_event(self, event_name = None, **kwargs): + """ + Immediately delete the specified event and cannot be restored. If there is a credential reference in the event, + it cannot be deleted. Please dissociate it first. + + Args: + :param event_name: The name of the event notification. + :type event_name: str + """ + try: + request = DeleteSecretEventRequest(event_name = event_name) + response = self.dew_client.cms_client.delete_secret_event(request) + self.logger.info("Successfully delete_secret_event:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def list_secret_events(self, marker = None, limit = None, **kwargs): + """ + Query all events created by the current user under this project + """ + try: + request = ListSecretEventsRequest() + request.limit =limit + request.marker = marker + response = self.dew_client.cms_client.list_secret_events(request) + self.logger.info("Successfully list_secret_events:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def show_secret_event(self, event_name = None, **kwargs): + """ + Query information for a specified event. + + Args: + :param event_name: The name of the event notification. + :type event_name: str + """ + try: + request = ShowSecretEventRequest(event_name = event_name) + response = self.dew_client.cms_client.show_secret_event(request) + self.logger.info("Successfully show_secret_event:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def update_secret_event(self, event_name = None, state = None, event_types = None, notification = None, **kwargs): + """ + Update metadata information for specified events. The metadata that supports updates includes event enable status, + basic type list, and notification topic. + + Args: + :param event_name: The name of the event notification. + :type event_name: str + """ + try: + request = UpdateSecretEventRequest(event_name = event_name) + request.body = UpdateSecretEventRequestBody( + state = state, + event_types = event_types, + notification = notification + ) + response = self.dew_client.cms_client.update_secret_event(request) + self.logger.info("Successfully update_secret_event:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def list_notification_records(self, marker = None, limit = None, **kwargs): + """ + Query triggered event notification records. + """ + try: + request = ListNotificationRecordsRequest( + limit = limit, + marker = marker + ) + response = self.dew_client.cms_client.list_notification_records(request) + self.logger.info("Successfully list_notification_records:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def batch_create_kms_tags(self, key_id = None, key = None, value = None, action = None, **kwargs): + """ + + Args: + :param key_id: key ID + :type key_id: str + + :param action: Operation identifier: limited to "create" and "delete". + :type action: str + + :param key: The name of the label. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + Value range from 1 to 128 characters, satisfying regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L}\\\\p{Z}\\\\p{N} + _.:=+\\\\-@]*)(?<!\\\\s)$\" + :type key: list[str] + """ + try: + request = BatchCreateKmsTagsRequest(key_id = key_id) + listTagsbody = [] + if isinstance(key,list): + for s in range(len(key)): + listTagsbody.append(TagItem(key =key[s], + value = value[s] if value is not None else None)) + else: + listTagsbody.append(TagItem(key =key, value = value)) + request.body = BatchCreateKmsTagsRequestBody( + action=action, + tags=listTagsbody + ) + response = self.dew_client.kms_client.batch_create_kms_tags(request) + self.logger.info("Successfully batch_create_kms_tags:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def create_kms_tag(self, key_id = None, key = None, value = None, **kwargs): + """ + Add key labels. + + Args: + :param key_id: key ID + :type key_id: str + + :param key: The name of the label. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + Value range from 1 to 128 characters, satisfying regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L}\\\\p{Z}\\\\p{N} + _.:=+\\\\-@]*)(?<!\\\\s)$\" + :type key: str + """ + try: + request = CreateKmsTagRequest(key_id = key_id) + tagbody = TagItem( + key = key, + value = value + ) + request.body = CreateKmsTagRequestBody( + tag=tagbody + ) + response = self.dew_client.kms_client.create_kms_tag(request) + self.logger.info("Successfully create_kms_tag:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def list_kms_tags(self, **kwargs): + """ + Query all label collections of the user under the specified project. + """ + try: + request = ListKmsTagsRequest() + response = self.dew_client.kms_client.list_kms_tags(request) + self.logger.info("Successfully list_kms_tags:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + def delete_tag(self, key_id = None, key = None, **kwargs): + """ + Delete key label. + + Args: + :param key_id: Key ID + :type key_id: str + :param key: Value of label key + :type key: str + """ + try: + request = DeleteTagRequest(key_id = key_id, key = key) + response = self.dew_client.kms_client.delete_tag(request) + self.logger.info("Successfully delete_tag:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + def list_kms_by_tags(self,key = None, values = None, limit=None, offset=None, action=None, tags=None, matches=None, sequence=None, **kwargs): + """ + Query key instances. Filter through tags to query detailed information about the specified user's master key. + """ + try: + request = ListKmsByTagsRequest(resource_instances = "resource_instances") + listTagsbody = [] + if isinstance(key,list): + for s in range(len(key)): + listTagsbody.append(Tag(key = key[s] if key is not None else None, + values = values[s] if values is not None else None)) + else: + listTagsbody.append(Tag(key = key, values = values)) + request.body = ListKmsByTagsRequestBody( + tags = listTagsbody if key is not None else None, + action = action, + offset = offset, + limit = limit, + sequence = sequence, + matches = matches + ) + response = self.dew_client.kms_client.list_kms_by_tags(request) + self.logger.info("Successfully list_kms_by_tags:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + def show_kms_tags(self, key_id = None, **kwargs): + """ + Query the key label. + + Args: + :param key_id: Key ID + :type key_id: str + """ + try: + request = ShowKmsTagsRequest(key_id = key_id) + response = self.dew_client.kms_client.show_kms_tags(request) + self.logger.info("Successfully show_kms_tags:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + + + def create_key_store(self, keystore_alias = None, hsm_cluster_id = None, hsm_ca_cert = None, **kwargs): + """" + Create a tenant exclusive key repository that uses DHSM instances as key storage. + + Args: + :param keystore_alias: Exclusive key repository alias, with a value range of 1 to 255 characters, satisfies regular matching + "^[a-zA-Z0-9:/_-]{1,255}$", and does not have the same name as existing exclusive key repository aliases. + :type keystore_alias: str + :param hsm_cluster_id: The DHSM cluster ID requires that the cluster has not yet created a dedicated key repository. + :type hsm_cluster_id: str + :param hsm_ca_cert: CA certificate for DHSM cluster + :type hsm_ca_cert: str + """ + try: + request = CreateKeyStoreRequest() + request.body = CreateKeyStoreRequestBody( + hsm_ca_cert = hsm_ca_cert, + hsm_cluster_id = hsm_cluster_id, + keystore_alias = keystore_alias + ) + response = self.dew_client.kms_client.create_key_store(request) + self.logger.info("Successfully create_key_store:") + self.logger.info(response) + return response + except exceptions.ClientRequestException as e: + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") \ No newline at end of file diff --git a/build/lib/prefect_huaweicloud/dew_client.py b/build/lib/prefect_huaweicloud/dew_client.py index 7aa3751..b933607 100644 --- a/build/lib/prefect_huaweicloud/dew_client.py +++ b/build/lib/prefect_huaweicloud/dew_client.py @@ -8,23 +8,22 @@ from huaweicloudsdkcsms.v1 import CsmsClient class DewClient(): - def __init__(self,region_id=None, ak=None, sk=None, *args, **kwargs): + def __init__(self,region_id = None, ak = None, sk = None, project_id = None, *args, **kwargs): if not ak or not sk: raise Exception("please input both huawei_cloud_access_key_id and huawei_cloud_secret_access_key") - self.region_id=region_id - self.__ak=ak - self.__sk=sk - self.kms_client=KmsClient.new_builder() \ - .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ + self.region_id = region_id + self.__ak = ak + self.__sk = sk + self.__project_id=project_id + self.kms_client = KmsClient.new_builder() \ + .with_credentials(BasicCredentials(self.__ak, self.__sk, self.__project_id)) \ .with_region(KmsRegion.value_of(self.region_id)) \ .build() - self.kps_client=KpsClient.new_builder() \ - .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ + self.kps_client = KpsClient.new_builder() \ + .with_credentials(BasicCredentials(self.__ak, self.__sk, self.__project_id)) \ .with_region(KpsRegion.value_of(self.region_id)) \ .build() - self.cms_client=CsmsClient.new_builder() \ - .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ + self.cms_client = CsmsClient.new_builder() \ + .with_credentials(BasicCredentials(self.__ak, self.__sk, self.__project_id)) \ .with_region(CsmsRegion.value_of(self.region_id)) \ .build() - - \ No newline at end of file diff --git a/build/lib/prefect_huaweicloud/test/__init__.py b/build/lib/prefect_huaweicloud/test/__init__.py index 3f591f7..92f0816 100644 --- a/build/lib/prefect_huaweicloud/test/__init__.py +++ b/build/lib/prefect_huaweicloud/test/__init__.py @@ -1,3 +1,4 @@ from prefect_huaweicloud.obs_block import ObsBlock from prefect_huaweicloud.dew_block import DewBlock -__all__ = ["ObsBlock","DewBlock"] \ No newline at end of file +from prefect_huaweicloud.dew_client import DewClient +__all__ = ["ObsBlock","DewBlock","DewClient"] \ No newline at end of file diff --git a/build/lib/prefect_huaweicloud/test/test_dew_block.py b/build/lib/prefect_huaweicloud/test/test_dew_block.py index fc955c1..bf90810 100644 --- a/build/lib/prefect_huaweicloud/test/test_dew_block.py +++ b/build/lib/prefect_huaweicloud/test/test_dew_block.py @@ -3,66 +3,125 @@ from pathlib import Path sys.path.append(str(Path(__file__).resolve().parents[1])) from dew_block import DewBlock from prefect import flow,task +def kms_params(huaweicloud_dew_block): + test_key = None + key_alias = None + if "key_alias" in huaweicloud_dew_block.dew_parameters: + key_alias = huaweicloud_dew_block.dew_parameters["key_alias"] + test_key = huaweicloud_dew_block.create_key(key_alias = key_alias) + return dict( + key_alias = key_alias if key_alias is not None else None, + key_id = test_key.key_info.key_id if test_key is not None else None, + key_description = None, + pending_days = huaweicloud_dew_block.dew_parameters["pending_days"] if "pending_days" in huaweicloud_dew_block.dew_parameters else None, + random_data_length = huaweicloud_dew_block.dew_parameters["random_data_length"] if "random_data_length" in huaweicloud_dew_block.dew_parameters else None, + datakey_length = huaweicloud_dew_block.dew_parameters["datakey_length"] if "datakey_length" in huaweicloud_dew_block.dew_parameters else None, + datakey_plain_length = huaweicloud_dew_block.dew_parameters["datakey_plain_length"] if "datakey_plain_length" in huaweicloud_dew_block.dew_parameters else None, + datakey_cipher_length = huaweicloud_dew_block.dew_parameters["datakey_cipher_length"] if "datakey_cipher_length" in huaweicloud_dew_block.dew_parameters else None, + cipher_text = None, + plain_text = None, + datakey_dgst = None, -def kms_params(huaweicloud_dew_block, key_alias=None,key_spec=None): - test_key=huaweicloud_dew_block.create_key(key_alias=key_alias) - return dict( - key_alias=key_alias, - key_id=test_key.key_info.key_id, - key_description=None, - pending_days=7, - random_data_length=512, - datakey_length=512, - datakey_plain_length=64, - datakey_cipher_length=64, - cipher_text=None, - plain_text=None, - datakey_dgst=None, - - grantee_principal="0f9eaeef3b7347f3804c2b27d126273e", - listOperationsbody = [ - "describe-key", - "create-datakey", - "encrypt-datakey"], - grant_id=None, - encryption_algorithm="SYMMETRIC_DEFAULT", - rotation_interval=30, - - signing_algorithm="RSASSA_PKCS1_V1_5_SHA_256", - message="09d158717e34db02afbe64c1d96b7a7cb3e846fb04f642b6257caccf1ca06485", - message_type="RAW", - signature=None + asymmetric_key_id=huaweicloud_dew_block.dew_parameters["asymmetric_key_id"] if "asymmetric_key_id" in huaweicloud_dew_block.dew_parameters else None, + + grantee_principal = huaweicloud_dew_block.dew_parameters["grantee_principal"] if "grantee_principal" in huaweicloud_dew_block.dew_parameters else None, + listOperationsbody = huaweicloud_dew_block.dew_parameters["listOperationsbody"] if "listOperationsbody" in huaweicloud_dew_block.dew_parameters else None, + grant_id = None, + rotation_interval = huaweicloud_dew_block.dew_parameters["rotation_interval"] if "rotation_interval" in huaweicloud_dew_block.dew_parameters else None, + + signing_algorithm = huaweicloud_dew_block.dew_parameters["signing_algorithm"] if "signing_algorithm" in huaweicloud_dew_block.dew_parameters else None, + message = huaweicloud_dew_block.dew_parameters["message"] if "message" in huaweicloud_dew_block.dew_parameters else None, + message_type = huaweicloud_dew_block.dew_parameters["message_type"] if "message_type" in huaweicloud_dew_block.dew_parameters else None, + signature = None, + + action = huaweicloud_dew_block.dew_parameters["action"] if "action" in huaweicloud_dew_block.dew_parameters else None, + key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, + version_id = huaweicloud_dew_block.dew_parameters["version_id"] if "version_id" in huaweicloud_dew_block.dew_parameters else None, ) -def kps_params(huaweicloud_dew_block, name): - key_pair_list=huaweicloud_dew_block.list_keypairs() - if name in list(x.keypair.name for x in key_pair_list.keypairs[:]): - huaweicloud_dew_block.delete_keypair(keypair_name=name) - test_key=huaweicloud_dew_block.create_keypair(name=name) +def kps_params(huaweicloud_dew_block): + key_pair_list = huaweicloud_dew_block.list_keypairs() + test_key = None + name = None + if "name" in huaweicloud_dew_block.dew_parameters: + name = huaweicloud_dew_block.dew_parameters["name"] + if name in list(x.keypair.name for x in key_pair_list.keypairs[:]): + huaweicloud_dew_block.delete_keypair(keypair_name = name) + test_key = huaweicloud_dew_block.create_keypair(name = name) + return dict( + name = name, + keypair_name = name, + private_key = test_key.keypair.private_key, + description = None, + id = huaweicloud_dew_block.dew_parameters["id"] if "id" in huaweicloud_dew_block.dew_parameters else None, + kms_key_name = huaweicloud_dew_block.dew_parameters["kms_key_name"] if "kms_key_name" in huaweicloud_dew_block.dew_parameters else None, + type = huaweicloud_dew_block.dew_parameters["type"] if "type" in huaweicloud_dew_block.dew_parameters else None, + key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, + task_id = None, + disable_password = huaweicloud_dew_block.dew_parameters["disable_password"] if "disable_password" in huaweicloud_dew_block.dew_parameters else None, + ) + + +def csms_params(huaweicloud_dew_block): + secret_list = huaweicloud_dew_block.list_secrets() + secret_string = None + event_name = None + test_secret = None + if "name" and "secret_string" in huaweicloud_dew_block.dew_parameters: + name = huaweicloud_dew_block.dew_parameters["name"] + secret_string = huaweicloud_dew_block.dew_parameters["secret_string"] + + if name in list(x.name for x in secret_list.secrets[:]): + huaweicloud_dew_block.delete_secret(secret_name = name) + test_secret = huaweicloud_dew_block.create_secret(name,secret_string = secret_string) + + secret_event = huaweicloud_dew_block.list_secret_events() + + if event_name in list(x.name for x in secret_event.events[:]): + huaweicloud_dew_block.delete_secret_event(event_name = event_name) return dict( - name=name, - keypair_name=name, - private_key=test_key.keypair.private_key, - description=None - ) + secret_name = test_secret.secret.name, + version_id = huaweicloud_dew_block.dew_parameters["version_id"] if "version_id" in huaweicloud_dew_block.dew_parameters else None, + secret_blob = None, + expire_time = huaweicloud_dew_block.dew_parameters["expire_time"] if "expire_time" in huaweicloud_dew_block.dew_parameters else None, + secret_string = secret_string, + stage_name = huaweicloud_dew_block.dew_parameters["stage_name"] if "stage_name" in huaweicloud_dew_block.dew_parameters else None, + update_stage_name=huaweicloud_dew_block.dew_parameters["update_stage_name"] if "update_stage_name" in huaweicloud_dew_block.dew_parameters else None, + update_version_id = huaweicloud_dew_block.dew_parameters["update_version_id"] if "update_version_id" in huaweicloud_dew_block.dew_parameters else None, + secret_id = test_secret.secret.id, + key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, + action = huaweicloud_dew_block.dew_parameters["action0"] if "action0" in huaweicloud_dew_block.dew_parameters else None, + action1=huaweicloud_dew_block.dew_parameters["action1"] if "action1" in huaweicloud_dew_block.dew_parameters else None, + + value = huaweicloud_dew_block.dew_parameters["value"] if "value" in huaweicloud_dew_block.dew_parameters else None, + values = huaweicloud_dew_block.dew_parameters["values"] if "values" in huaweicloud_dew_block.dew_parameters else None, + resource_instances = huaweicloud_dew_block.dew_parameters["resource_instances"] if "resource_instances" in huaweicloud_dew_block.dew_parameters else None, + event_name = huaweicloud_dew_block.dew_parameters["event_name"] if "event_name" in huaweicloud_dew_block.dew_parameters else None, + event_types = huaweicloud_dew_block.dew_parameters["event_types"] if "event_types" in huaweicloud_dew_block.dew_parameters else None, + state = huaweicloud_dew_block.dew_parameters["state"] if "state" in huaweicloud_dew_block.dew_parameters else None, + target_type = huaweicloud_dew_block.dew_parameters["target_type"] if "target_type" in huaweicloud_dew_block.dew_parameters else None, + target_id = huaweicloud_dew_block.dew_parameters["target_id"] if "target_id" in huaweicloud_dew_block.dew_parameters else None, + target_name = huaweicloud_dew_block.dew_parameters["target_name"] if "target_name" in huaweicloud_dew_block.dew_parameters else None, + recovery_window_in_days = huaweicloud_dew_block.dew_parameters["recovery_window_in_days"] if "recovery_window_in_days" in huaweicloud_dew_block.dew_parameters else None, + ) @flow def test_key_lifecycle_management(kms_params, huaweicloud_dew_block): - row_key_alias=kms_params['key_alias'] + row_key_alias = kms_params['key_alias'] huaweicloud_dew_block.create_key(**kms_params) huaweicloud_dew_block.disable_key(**kms_params) huaweicloud_dew_block.enable_key(**kms_params) - kms_params['key_alias']="test_alias" + kms_params['key_alias'] = "test_alias" huaweicloud_dew_block.update_key_Alias(**kms_params) - kms_params['key_alias']=row_key_alias + kms_params['key_alias'] = row_key_alias huaweicloud_dew_block.update_key_Alias(**kms_params) - kms_params['key_description']="test_update_description" + kms_params['key_description'] = "test_update_description" huaweicloud_dew_block.update_key_description(**kms_params) - huaweicloud_dew_block.delete_key(**kms_params) + huaweicloud_dew_block.delete_key(**kms_params) huaweicloud_dew_block.cancel_key_deletion(**kms_params) huaweicloud_dew_block.enable_key(**kms_params) @@ -70,44 +129,54 @@ def test_key_lifecycle_management(kms_params, huaweicloud_dew_block): @flow def test_data_key_management(kms_params, huaweicloud_dew_block): huaweicloud_dew_block.create_data_key_without_plaintext(**kms_params) - create_data_key_response=huaweicloud_dew_block.create_data_key(**kms_params) + create_data_key_response = huaweicloud_dew_block.create_data_key(**kms_params) huaweicloud_dew_block.create_random(**kms_params) - kms_params["cipher_text"]=create_data_key_response.cipher_text - decrypt_data_key_response=huaweicloud_dew_block.decrypt_data_key(**kms_params) - kms_params["datakey_dgst"]=decrypt_data_key_response.datakey_dgst - kms_params["plain_text"]=decrypt_data_key_response.data_key+decrypt_data_key_response.datakey_dgst + kms_params["cipher_text"] = create_data_key_response.cipher_text + decrypt_data_key_response = huaweicloud_dew_block.decrypt_data_key(**kms_params) + kms_params["datakey_dgst"] = decrypt_data_key_response.datakey_dgst + kms_params["plain_text"] = decrypt_data_key_response.data_key+decrypt_data_key_response.datakey_dgst huaweicloud_dew_block.encrypt_data_key(**kms_params) @flow def test_key_grant_management(kms_params, huaweicloud_dew_block): - create_grant_response=huaweicloud_dew_block.create_grant(**kms_params) - kms_params["grant_id"]=create_grant_response.grant_id + create_grant_response = huaweicloud_dew_block.create_grant(**kms_params) + kms_params["grant_id"] = create_grant_response.grant_id huaweicloud_dew_block.list_retirable_grants(**kms_params) - # huaweicloud_dew_block.cancel_self_grant(**kms_params) + huaweicloud_dew_block.cancel_self_grant(**kms_params) + huaweicloud_dew_block.create_grant(**kms_params) huaweicloud_dew_block.cancel_grant(**kms_params) huaweicloud_dew_block.list_grants(**kms_params) @flow def test_key_pair_management(kps_params, huaweicloud_dew_block): - row_keypair_name=kps_params['name'] - huaweicloud_dew_block.import_private_key(**kps_params) + huaweicloud_dew_block.import_private_key(**kps_params) huaweicloud_dew_block.export_private_key(**kps_params) huaweicloud_dew_block.list_keypair_detail(**kps_params) huaweicloud_dew_block.list_keypairs(**kps_params) huaweicloud_dew_block.clear_private_key(**kps_params) - - kps_params['description']="test_update_description" - huaweicloud_dew_block.update_keypair_description(**kps_params) - + + kps_params['description'] = "test_update_description" + huaweicloud_dew_block.update_keypair_description(**kps_params) + huaweicloud_dew_block.delete_keypair(**kps_params) +@flow +def test_key_pair_task_management(kps_params, huaweicloud_dew_block): + kps_params["task_id"] = huaweicloud_dew_block.associate_keypair(**kps_params).task_id + huaweicloud_dew_block.batch_associate_keypair(**kps_params) + # huaweicloud_dew_block.delete_failed_task(**kps_params) + huaweicloud_dew_block.delete_all_failed_task(**kps_params) + huaweicloud_dew_block.disassociate_keypair(**kps_params) + huaweicloud_dew_block.list_failed_task(**kps_params) + huaweicloud_dew_block.list_keypair_task(**kps_params) + huaweicloud_dew_block.list_running_task(**kps_params) @flow def test_small_data_encryption(kms_params, huaweicloud_dew_block): - encrypt_data_response=huaweicloud_dew_block.encrypt_data(**kms_params) - kms_params["cipher_text"]=encrypt_data_response.cipher_text + encrypt_data_response = huaweicloud_dew_block.encrypt_data(**kms_params) + kms_params["cipher_text"] = encrypt_data_response.cipher_text huaweicloud_dew_block.decrypt_data(**kms_params) @@ -116,38 +185,113 @@ def test_small_data_encryption(kms_params, huaweicloud_dew_block): def test_list_key(kms_params, huaweicloud_dew_block): huaweicloud_dew_block.list_keys(**kms_params) huaweicloud_dew_block.list_key_detail(**kms_params) - huaweicloud_dew_block.show_public_key(key_id="95afc13e-a5ed-4271-b8e9-a71079e8c6b3") + huaweicloud_dew_block.show_public_key(**kms_params) huaweicloud_dew_block.show_user_instances(**kms_params) huaweicloud_dew_block.show_user_quotas(**kms_params) @flow def test_key_rotation_management(kms_params, huaweicloud_dew_block): - huaweicloud_dew_block.enable_key_rotation(**kms_params) + huaweicloud_dew_block.enable_key_rotation(**kms_params) huaweicloud_dew_block.show_key_rotation_status(**kms_params) huaweicloud_dew_block.update_key_rotation_interval(**kms_params) huaweicloud_dew_block.disable_key_rotation(**kms_params) @flow -def test_signature_verification(kms_params,huaweicloud_dew_block): - kms_params["key_id"]="95afc13e-a5ed-4271-b8e9-a71079e8c6b3" - row_sign=huaweicloud_dew_block.sign(**kms_params) - kms_params['signature']=row_sign.signature +def test_signature_verification(kms_params, huaweicloud_dew_block): + kms_params["key_id"] = "95afc13e-a5ed-4271-b8e9-a71079e8c6b3" + row_sign = huaweicloud_dew_block.sign(**kms_params) + kms_params['signature'] = row_sign.signature huaweicloud_dew_block.validate_signature(**kms_params) +@flow +def test_lifecycle_management(csms_params, huaweicloud_dew_block): + huaweicloud_dew_block.show_secret(**csms_params) + csms_params["secret_blob"] = huaweicloud_dew_block.download_secret_blob(**csms_params).secret_blob + huaweicloud_dew_block.update_secret(**csms_params) + huaweicloud_dew_block.delete_secret_for_schedule(**csms_params) + huaweicloud_dew_block.restore_secret(**csms_params) + huaweicloud_dew_block.delete_secret(**csms_params) + huaweicloud_dew_block.upload_secret_blob(**csms_params) + + +@flow +def test_credential_version_management(csms_params, huaweicloud_dew_block): + huaweicloud_dew_block.create_secret_version(**csms_params) + huaweicloud_dew_block.show_secret_version(**csms_params) + huaweicloud_dew_block.list_secret_versions(**csms_params) + huaweicloud_dew_block.update_version(**csms_params) + -if __name__=="__main__": +@flow +def test_credential_version_status_management(csms_params, huaweicloud_dew_block): + show_secret_stage_response = huaweicloud_dew_block.show_secret_stage(**csms_params) + csms_params["stage_name"] = csms_params["update_stage_name"] + csms_params["version_id"] = show_secret_stage_response.stage.version_id + huaweicloud_dew_block.update_secret_stage(**csms_params) + huaweicloud_dew_block.delete_secret_stage(**csms_params) + + +@flow +def test_voucher_label_management(csms_params, huaweicloud_dew_block): + huaweicloud_dew_block.batch_create_or_delete_tags(**csms_params) + huaweicloud_dew_block.create_secret_tag(**csms_params) + huaweicloud_dew_block.list_project_secrets_tags(**csms_params) + huaweicloud_dew_block.list_resource_instances(csms_params["resource_instances"],action=csms_params["action1"]) + huaweicloud_dew_block.list_secret_tags(**csms_params) + huaweicloud_dew_block.delete_secret_tag(**csms_params) + + +@flow +def test_event_management(csms_params, huaweicloud_dew_block): + huaweicloud_dew_block.create_secret_event(**csms_params) + huaweicloud_dew_block.show_secret_event(**csms_params) + huaweicloud_dew_block.update_secret_event(**csms_params) + huaweicloud_dew_block.delete_secret_event(**csms_params) + huaweicloud_dew_block.list_notification_records(**csms_params) + + +@flow +def test_key_label_management(kms_params, huaweicloud_dew_block): + huaweicloud_dew_block.list_kms_tags(**kms_params) + huaweicloud_dew_block.batch_create_kms_tags(**kms_params) + huaweicloud_dew_block.create_kms_tag(**kms_params) + huaweicloud_dew_block.list_kms_by_tags(action = "count") + huaweicloud_dew_block.show_kms_tags(**kms_params) + huaweicloud_dew_block.delete_tag(**kms_params) + +@flow +def test_query_key_api_version_information(kms_params, huaweicloud_dew_block): + huaweicloud_dew_block.show_versions(**kms_params) + huaweicloud_dew_block.show_version(**kms_params) + + +if __name__ == "__main__": huaweicloud_dew_block = DewBlock.load("test-dew-block") - kms_params=kms_params(huaweicloud_dew_block, key_alias="1-9") - kps_params=kps_params(huaweicloud_dew_block, name="22-22") -# test_key_lifecycle_management(kms_params,huaweicloud_dew_block) - test_key_pair_management(kps_params,huaweicloud_dew_block) -# test_data_key_management(kms_params,huaweicloud_dew_block) -# test_key_grant_management(kms_params,huaweicloud_dew_block) -# test_small_data_encryption(kms_params,huaweicloud_dew_block) -# test_list_key(kms_params, huaweicloud_dew_block) -# test_key_rotation_management(kms_params, huaweicloud_dew_block) -# test_signature_verification(kms_params, huaweicloud_dew_block) - \ No newline at end of file + + # test_key_lifecycle_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_data_key_management(kms_params, huaweicloud_dew_block) + # test_small_data_encryption(kms_params, huaweicloud_dew_block) + # test_list_key(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_query_key_api_version_information(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_key_grant_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_signature_verification(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_key_label_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_key_rotation_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) + + + # test_key_pair_task_management(kps_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_key_pair_management(kps_params(huaweicloud_dew_block), huaweicloud_dew_block) + + # csms_params = csms_params(huaweicloud_dew_block, name = "demo", secret_string = "test_secret", secret_type = None, event_name = "demo_event") + # test_credential_version_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_lifecycle_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_credential_version_status_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_voucher_label_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_event_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) + + + + diff --git a/dist/prefect_hwc-0.1.0-py3.12.egg b/dist/prefect_hwc-0.1.0-py3.12.egg new file mode 100644 index 0000000000000000000000000000000000000000..8bf54a6cbd6f7e25a0b23384b640890dfb6df0a4 GIT binary patch literal 43323 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 literal 0 HcmV?d00001 diff --git a/prefect_huaweicloud/dew_block.py b/prefect_huaweicloud/dew_block.py index 307f3ca..799a053 100644 --- a/prefect_huaweicloud/dew_block.py +++ b/prefect_huaweicloud/dew_block.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Optional, Dict, Any from logging import Logger from pydantic import Field, SecretStr from prefect.blocks.abstract import Block @@ -34,6 +34,11 @@ class DewBlock(Block): description = "A specific Huawei Cloud secret access key.", title = "Huawei Cloud Access Key Secret:", ) + huawei_cloud_project_id: Optional[SecretStr] = Field( + default=None, + description = "A specific Huawei Cloud project id.", + title="Huawei Cloud project id", + ) huawei_cloud_security_token: Optional[SecretStr] = Field( default = None, description = "SecurityToken in the temporary access key, " @@ -44,12 +49,17 @@ class DewBlock(Block): default = None, title = "region id", ) - + huawei_cloud_dew_parameters: Optional[Dict[str, Any]] = Field( + default=None, + description="Extra parameters for using dew.", + title="dew_parameters", + ) def __init__(self, *args, **kwargs): self.dew_client = DewClient(region_id = kwargs['region_id'], ak = kwargs['huawei_cloud_access_key_id'], - sk = kwargs['huawei_cloud_secret_access_key']) - + sk = kwargs['huawei_cloud_secret_access_key'], + project_id = kwargs['huawei_cloud_project_id'] if kwargs.get('huawei_cloud_project_id') else None) + self.dew_parameters = kwargs['huawei_cloud_dew_parameters'] if kwargs.get('huawei_cloud_project_id') else None @property def logger(self) -> Logger: """ @@ -670,7 +680,7 @@ class DewBlock(Block): self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - def sign(self, key_id = None, message = None, signing_algorithm = None, message_type = None, sequence = None, **kwargs): + def sign(self, asymmetric_key_id = None, message = None, signing_algorithm = None, message_type = None, sequence = None, **kwargs): """ Digitally sign a message or message digest using a private key with an asymmetric key. @@ -694,7 +704,7 @@ class DewBlock(Block): request.body = SignRequestBody( signing_algorithm = signing_algorithm, message = message, - key_id = key_id, + key_id = asymmetric_key_id, message_type = message_type, sequence = sequence ) @@ -706,7 +716,7 @@ class DewBlock(Block): self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - def validate_signature(self, key_id = None, message = None, signature = None, signing_algorithm = None, + def validate_signature(self, asymmetric_key_id = None, message = None, signature = None, signing_algorithm = None, message_type = None, sequence = None, **kwargs): """ Verify the signature of a message or message digest using a public key with an asymmetric key. @@ -732,7 +742,7 @@ class DewBlock(Block): try: request = ValidateSignatureRequest() request.body = VerifyRequestBody( - key_id = key_id, + key_id = asymmetric_key_id, message = message, signature = signature, signing_algorithm = signing_algorithm, @@ -793,7 +803,7 @@ class DewBlock(Block): self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_public_key(self, key_id = None, sequence = None, **kwargs): + def show_public_key(self, asymmetric_key_id = None, sequence = None, **kwargs): """ Query public key information for user specified asymmetric keys. @@ -806,7 +816,7 @@ class DewBlock(Block): try: request = ShowPublicKeyRequest() request.body = OperateKeyRequestBody( - key_id = key_id, + key_id = asymmetric_key_id, sequence = sequence ) response = self.dew_client.kms_client.show_public_key(request) @@ -1040,7 +1050,7 @@ class DewBlock(Block): self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - def import_private_key(self, user_id = None, name = None,type = "default", kms_key_name = "kps/default", private_key = None, **kwargs): + def import_private_key(self, user_id = None, name = None,type = None, kms_key_name = None, private_key = None, **kwargs): """ Import the private key into the specified key pair. @@ -1094,7 +1104,7 @@ class DewBlock(Block): try: request = ListKeypairDetailRequest(keypair_name = keypair_name) response = self.dew_client.kps_client.list_keypair_detail(request) - self.logger.info("Successfully list private key detail:") + self.logger.info("Successfully list_keypair_detail") self.logger.info(response) return response except exceptions.ClientRequestException as e: @@ -1504,7 +1514,7 @@ class DewBlock(Block): error_code = {e.error_code}, error_msg = {e.error_msg}") def create_secret_event(self, target_type = None, target_id = None, - target_name = None, name = None, state = None, + target_name = None, event_name = None, state = None, event_types = None, **kwargs): """ Create an event that can be configured on one or more credential objects. When an event is enabled and the @@ -1545,7 +1555,7 @@ class DewBlock(Block): notification = notification_body, state = state, event_types = event_types, - name = name, + name = event_name, ) response = self.dew_client.cms_client.create_secret_event(request) self.logger.info("Successfully create_secret_event:") diff --git a/prefect_huaweicloud/dew_client.py b/prefect_huaweicloud/dew_client.py index 28feb9b..b933607 100644 --- a/prefect_huaweicloud/dew_client.py +++ b/prefect_huaweicloud/dew_client.py @@ -8,23 +8,22 @@ from huaweicloudsdkcsms.v1 import CsmsClient class DewClient(): - def __init__(self,region_id = None, ak = None, sk = None, *args, **kwargs): + def __init__(self,region_id = None, ak = None, sk = None, project_id = None, *args, **kwargs): if not ak or not sk: raise Exception("please input both huawei_cloud_access_key_id and huawei_cloud_secret_access_key") self.region_id = region_id self.__ak = ak self.__sk = sk + self.__project_id=project_id self.kms_client = KmsClient.new_builder() \ - .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ + .with_credentials(BasicCredentials(self.__ak, self.__sk, self.__project_id)) \ .with_region(KmsRegion.value_of(self.region_id)) \ .build() self.kps_client = KpsClient.new_builder() \ - .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ + .with_credentials(BasicCredentials(self.__ak, self.__sk, self.__project_id)) \ .with_region(KpsRegion.value_of(self.region_id)) \ .build() self.cms_client = CsmsClient.new_builder() \ - .with_credentials(BasicCredentials(self.__ak,self.__sk)) \ + .with_credentials(BasicCredentials(self.__ak, self.__sk, self.__project_id)) \ .with_region(CsmsRegion.value_of(self.region_id)) \ .build() - - \ No newline at end of file diff --git a/prefect_huaweicloud/test/__init__.py b/prefect_huaweicloud/test/__init__.py index 3f591f7..92f0816 100644 --- a/prefect_huaweicloud/test/__init__.py +++ b/prefect_huaweicloud/test/__init__.py @@ -1,3 +1,4 @@ from prefect_huaweicloud.obs_block import ObsBlock from prefect_huaweicloud.dew_block import DewBlock -__all__ = ["ObsBlock","DewBlock"] \ No newline at end of file +from prefect_huaweicloud.dew_client import DewClient +__all__ = ["ObsBlock","DewBlock","DewClient"] \ No newline at end of file diff --git a/prefect_huaweicloud/test/test_dew_block.py b/prefect_huaweicloud/test/test_dew_block.py index d890310..bf90810 100644 --- a/prefect_huaweicloud/test/test_dew_block.py +++ b/prefect_huaweicloud/test/test_dew_block.py @@ -3,70 +3,80 @@ from pathlib import Path sys.path.append(str(Path(__file__).resolve().parents[1])) from dew_block import DewBlock from prefect import flow,task - - -def kms_params(huaweicloud_dew_block, key_alias = None,key_spec = None): - test_key = huaweicloud_dew_block.create_key(key_alias = key_alias) +def kms_params(huaweicloud_dew_block): + test_key = None + key_alias = None + if "key_alias" in huaweicloud_dew_block.dew_parameters: + key_alias = huaweicloud_dew_block.dew_parameters["key_alias"] + test_key = huaweicloud_dew_block.create_key(key_alias = key_alias) return dict( - key_alias = key_alias, - key_id = test_key.key_info.key_id, + key_alias = key_alias if key_alias is not None else None, + key_id = test_key.key_info.key_id if test_key is not None else None, key_description = None, - pending_days = 7, - random_data_length = 512, - datakey_length = 512, - datakey_plain_length = 64, - datakey_cipher_length = 64, + pending_days = huaweicloud_dew_block.dew_parameters["pending_days"] if "pending_days" in huaweicloud_dew_block.dew_parameters else None, + + random_data_length = huaweicloud_dew_block.dew_parameters["random_data_length"] if "random_data_length" in huaweicloud_dew_block.dew_parameters else None, + datakey_length = huaweicloud_dew_block.dew_parameters["datakey_length"] if "datakey_length" in huaweicloud_dew_block.dew_parameters else None, + datakey_plain_length = huaweicloud_dew_block.dew_parameters["datakey_plain_length"] if "datakey_plain_length" in huaweicloud_dew_block.dew_parameters else None, + datakey_cipher_length = huaweicloud_dew_block.dew_parameters["datakey_cipher_length"] if "datakey_cipher_length" in huaweicloud_dew_block.dew_parameters else None, cipher_text = None, plain_text = None, datakey_dgst = None, - grantee_principal = "0f9eaeef3b7347f3804c2b27d126273e", - listOperationsbody = [ - "describe-key", - "create-datakey", - "encrypt-datakey"], + asymmetric_key_id=huaweicloud_dew_block.dew_parameters["asymmetric_key_id"] if "asymmetric_key_id" in huaweicloud_dew_block.dew_parameters else None, + + grantee_principal = huaweicloud_dew_block.dew_parameters["grantee_principal"] if "grantee_principal" in huaweicloud_dew_block.dew_parameters else None, + listOperationsbody = huaweicloud_dew_block.dew_parameters["listOperationsbody"] if "listOperationsbody" in huaweicloud_dew_block.dew_parameters else None, grant_id = None, - encryption_algorithm = "SYMMETRIC_DEFAULT", - rotation_interval = 30, - signing_algorithm = "RSASSA_PKCS1_V1_5_SHA_256", - message = "09d158717e34db02afbe64c1d96b7a7cb3e846fb04f642b6257caccf1ca06485", - message_type = "RAW", - signature = None, - recovery_window_in_days = 7, - action = "create", - key = "key0", - version_id = "v1.0", - keystore_alias="keystore_alias_01", + rotation_interval = huaweicloud_dew_block.dew_parameters["rotation_interval"] if "rotation_interval" in huaweicloud_dew_block.dew_parameters else None, - + signing_algorithm = huaweicloud_dew_block.dew_parameters["signing_algorithm"] if "signing_algorithm" in huaweicloud_dew_block.dew_parameters else None, + message = huaweicloud_dew_block.dew_parameters["message"] if "message" in huaweicloud_dew_block.dew_parameters else None, + message_type = huaweicloud_dew_block.dew_parameters["message_type"] if "message_type" in huaweicloud_dew_block.dew_parameters else None, + signature = None, + action = huaweicloud_dew_block.dew_parameters["action"] if "action" in huaweicloud_dew_block.dew_parameters else None, + key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, + version_id = huaweicloud_dew_block.dew_parameters["version_id"] if "version_id" in huaweicloud_dew_block.dew_parameters else None, ) -def kps_params(huaweicloud_dew_block, name): +def kps_params(huaweicloud_dew_block): key_pair_list = huaweicloud_dew_block.list_keypairs() - if name in list(x.keypair.name for x in key_pair_list.keypairs[:]): - huaweicloud_dew_block.delete_keypair(keypair_name = name) - test_key = huaweicloud_dew_block.create_keypair(name = name) + test_key = None + name = None + if "name" in huaweicloud_dew_block.dew_parameters: + name = huaweicloud_dew_block.dew_parameters["name"] + if name in list(x.keypair.name for x in key_pair_list.keypairs[:]): + huaweicloud_dew_block.delete_keypair(keypair_name = name) + test_key = huaweicloud_dew_block.create_keypair(name = name) return dict( name = name, keypair_name = name, private_key = test_key.keypair.private_key, description = None, - id = "59d5bfcf-20c9-427f-9ea6-a4f02504a9ea", - type = "password", - key = "Lky523175094", + id = huaweicloud_dew_block.dew_parameters["id"] if "id" in huaweicloud_dew_block.dew_parameters else None, + kms_key_name = huaweicloud_dew_block.dew_parameters["kms_key_name"] if "kms_key_name" in huaweicloud_dew_block.dew_parameters else None, + type = huaweicloud_dew_block.dew_parameters["type"] if "type" in huaweicloud_dew_block.dew_parameters else None, + key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, task_id = None, - disable_password = False, - ) + disable_password = huaweicloud_dew_block.dew_parameters["disable_password"] if "disable_password" in huaweicloud_dew_block.dew_parameters else None, + ) -def csms_params(huaweicloud_dew_block, name,secret_string, secret_type,event_name): +def csms_params(huaweicloud_dew_block): secret_list = huaweicloud_dew_block.list_secrets() - if name in list(x.name for x in secret_list.secrets[:]): - huaweicloud_dew_block.delete_secret(secret_name = name) - test_secret = huaweicloud_dew_block.create_secret(name,secret_string = secret_string,secret_type = secret_type) + secret_string = None + event_name = None + test_secret = None + if "name" and "secret_string" in huaweicloud_dew_block.dew_parameters: + name = huaweicloud_dew_block.dew_parameters["name"] + secret_string = huaweicloud_dew_block.dew_parameters["secret_string"] + + if name in list(x.name for x in secret_list.secrets[:]): + huaweicloud_dew_block.delete_secret(secret_name = name) + test_secret = huaweicloud_dew_block.create_secret(name,secret_string = secret_string) secret_event = huaweicloud_dew_block.list_secret_events() @@ -74,26 +84,29 @@ def csms_params(huaweicloud_dew_block, name,secret_string, secret_type,event_nam huaweicloud_dew_block.delete_secret_event(event_name = event_name) return dict( secret_name = test_secret.secret.name, - version_id = "v2", + version_id = huaweicloud_dew_block.dew_parameters["version_id"] if "version_id" in huaweicloud_dew_block.dew_parameters else None, secret_blob = None, - expire_time = None, + expire_time = huaweicloud_dew_block.dew_parameters["expire_time"] if "expire_time" in huaweicloud_dew_block.dew_parameters else None, secret_string = secret_string, - stage_name = "SYSCURRENT", + stage_name = huaweicloud_dew_block.dew_parameters["stage_name"] if "stage_name" in huaweicloud_dew_block.dew_parameters else None, + update_stage_name=huaweicloud_dew_block.dew_parameters["update_stage_name"] if "update_stage_name" in huaweicloud_dew_block.dew_parameters else None, + update_version_id = huaweicloud_dew_block.dew_parameters["update_version_id"] if "update_version_id" in huaweicloud_dew_block.dew_parameters else None, secret_id = test_secret.secret.id, - key = "tag2024", - action = "create", - value = "tag2024", - values = "tag2024", - resource_instances = "resource_instances", - name = "demo_event", - event_types = ["SECRET_VERSION_CREATED"], - state = "ENABLED", - target_type = "SMN", - target_id = "urn:smn:cn-south-1:SecertExpirationTest", - target_name = "SecertExpirationNotificationTest", - - - event_name = "demo_event" + key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, + action = huaweicloud_dew_block.dew_parameters["action0"] if "action0" in huaweicloud_dew_block.dew_parameters else None, + action1=huaweicloud_dew_block.dew_parameters["action1"] if "action1" in huaweicloud_dew_block.dew_parameters else None, + + value = huaweicloud_dew_block.dew_parameters["value"] if "value" in huaweicloud_dew_block.dew_parameters else None, + values = huaweicloud_dew_block.dew_parameters["values"] if "values" in huaweicloud_dew_block.dew_parameters else None, + resource_instances = huaweicloud_dew_block.dew_parameters["resource_instances"] if "resource_instances" in huaweicloud_dew_block.dew_parameters else None, + event_name = huaweicloud_dew_block.dew_parameters["event_name"] if "event_name" in huaweicloud_dew_block.dew_parameters else None, + event_types = huaweicloud_dew_block.dew_parameters["event_types"] if "event_types" in huaweicloud_dew_block.dew_parameters else None, + state = huaweicloud_dew_block.dew_parameters["state"] if "state" in huaweicloud_dew_block.dew_parameters else None, + target_type = huaweicloud_dew_block.dew_parameters["target_type"] if "target_type" in huaweicloud_dew_block.dew_parameters else None, + target_id = huaweicloud_dew_block.dew_parameters["target_id"] if "target_id" in huaweicloud_dew_block.dew_parameters else None, + target_name = huaweicloud_dew_block.dew_parameters["target_name"] if "target_name" in huaweicloud_dew_block.dew_parameters else None, + recovery_window_in_days = huaweicloud_dew_block.dew_parameters["recovery_window_in_days"] if "recovery_window_in_days" in huaweicloud_dew_block.dew_parameters else None, + ) @flow @@ -108,7 +121,7 @@ def test_key_lifecycle_management(kms_params, huaweicloud_dew_block): huaweicloud_dew_block.update_key_Alias(**kms_params) kms_params['key_description'] = "test_update_description" huaweicloud_dew_block.update_key_description(**kms_params) - huaweicloud_dew_block.delete_key(**kms_params) + huaweicloud_dew_block.delete_key(**kms_params) huaweicloud_dew_block.cancel_key_deletion(**kms_params) huaweicloud_dew_block.enable_key(**kms_params) @@ -118,7 +131,7 @@ def test_data_key_management(kms_params, huaweicloud_dew_block): huaweicloud_dew_block.create_data_key_without_plaintext(**kms_params) create_data_key_response = huaweicloud_dew_block.create_data_key(**kms_params) huaweicloud_dew_block.create_random(**kms_params) - kms_params["cipher_text"] = create_data_key_response.cipher_text + kms_params["cipher_text"] = create_data_key_response.cipher_text decrypt_data_key_response = huaweicloud_dew_block.decrypt_data_key(**kms_params) kms_params["datakey_dgst"] = decrypt_data_key_response.datakey_dgst kms_params["plain_text"] = decrypt_data_key_response.data_key+decrypt_data_key_response.datakey_dgst @@ -131,32 +144,32 @@ def test_key_grant_management(kms_params, huaweicloud_dew_block): kms_params["grant_id"] = create_grant_response.grant_id huaweicloud_dew_block.list_retirable_grants(**kms_params) huaweicloud_dew_block.cancel_self_grant(**kms_params) + huaweicloud_dew_block.create_grant(**kms_params) huaweicloud_dew_block.cancel_grant(**kms_params) huaweicloud_dew_block.list_grants(**kms_params) @flow def test_key_pair_management(kps_params, huaweicloud_dew_block): - row_keypair_name = kps_params['name'] - huaweicloud_dew_block.import_private_key(**kps_params) + huaweicloud_dew_block.import_private_key(**kps_params) huaweicloud_dew_block.export_private_key(**kps_params) huaweicloud_dew_block.list_keypair_detail(**kps_params) huaweicloud_dew_block.list_keypairs(**kps_params) huaweicloud_dew_block.clear_private_key(**kps_params) - + kps_params['description'] = "test_update_description" - huaweicloud_dew_block.update_keypair_description(**kps_params) - + huaweicloud_dew_block.update_keypair_description(**kps_params) + huaweicloud_dew_block.delete_keypair(**kps_params) @flow def test_key_pair_task_management(kps_params, huaweicloud_dew_block): - kps_params["task_id"] = huaweicloud_dew_block.associate_keypair(**kps_params).task_id + kps_params["task_id"] = huaweicloud_dew_block.associate_keypair(**kps_params).task_id huaweicloud_dew_block.batch_associate_keypair(**kps_params) - huaweicloud_dew_block.delete_all_failed_task(**kps_params) - huaweicloud_dew_block.delete_failed_task(**kps_params) - huaweicloud_dew_block.disassociate_keypair(**kps_params) - huaweicloud_dew_block.list_failed_task(**kps_params) + # huaweicloud_dew_block.delete_failed_task(**kps_params) + huaweicloud_dew_block.delete_all_failed_task(**kps_params) + huaweicloud_dew_block.disassociate_keypair(**kps_params) + huaweicloud_dew_block.list_failed_task(**kps_params) huaweicloud_dew_block.list_keypair_task(**kps_params) huaweicloud_dew_block.list_running_task(**kps_params) @@ -172,14 +185,14 @@ def test_small_data_encryption(kms_params, huaweicloud_dew_block): def test_list_key(kms_params, huaweicloud_dew_block): huaweicloud_dew_block.list_keys(**kms_params) huaweicloud_dew_block.list_key_detail(**kms_params) - huaweicloud_dew_block.show_public_key(key_id = "95afc13e-a5ed-4271-b8e9-a71079e8c6b3") + huaweicloud_dew_block.show_public_key(**kms_params) huaweicloud_dew_block.show_user_instances(**kms_params) huaweicloud_dew_block.show_user_quotas(**kms_params) @flow def test_key_rotation_management(kms_params, huaweicloud_dew_block): - huaweicloud_dew_block.enable_key_rotation(**kms_params) + huaweicloud_dew_block.enable_key_rotation(**kms_params) huaweicloud_dew_block.show_key_rotation_status(**kms_params) huaweicloud_dew_block.update_key_rotation_interval(**kms_params) huaweicloud_dew_block.disable_key_rotation(**kms_params) @@ -197,7 +210,7 @@ def test_signature_verification(kms_params, huaweicloud_dew_block): def test_lifecycle_management(csms_params, huaweicloud_dew_block): huaweicloud_dew_block.show_secret(**csms_params) csms_params["secret_blob"] = huaweicloud_dew_block.download_secret_blob(**csms_params).secret_blob - huaweicloud_dew_block.update_secret(**csms_params) + huaweicloud_dew_block.update_secret(**csms_params) huaweicloud_dew_block.delete_secret_for_schedule(**csms_params) huaweicloud_dew_block.restore_secret(**csms_params) huaweicloud_dew_block.delete_secret(**csms_params) @@ -209,16 +222,15 @@ def test_credential_version_management(csms_params, huaweicloud_dew_block): huaweicloud_dew_block.create_secret_version(**csms_params) huaweicloud_dew_block.show_secret_version(**csms_params) huaweicloud_dew_block.list_secret_versions(**csms_params) - csms_params["expire_time"] = 1705868739000 huaweicloud_dew_block.update_version(**csms_params) @flow def test_credential_version_status_management(csms_params, huaweicloud_dew_block): - huaweicloud_dew_block.show_secret_stage(**csms_params) - csms_params["version_id"] = "v1" + show_secret_stage_response = huaweicloud_dew_block.show_secret_stage(**csms_params) + csms_params["stage_name"] = csms_params["update_stage_name"] + csms_params["version_id"] = show_secret_stage_response.stage.version_id huaweicloud_dew_block.update_secret_stage(**csms_params) - csms_params["stage_name"] = "ACTIVE" huaweicloud_dew_block.delete_secret_stage(**csms_params) @@ -227,7 +239,7 @@ def test_voucher_label_management(csms_params, huaweicloud_dew_block): huaweicloud_dew_block.batch_create_or_delete_tags(**csms_params) huaweicloud_dew_block.create_secret_tag(**csms_params) huaweicloud_dew_block.list_project_secrets_tags(**csms_params) - huaweicloud_dew_block.list_resource_instances(resource_instances = "resource_instances", action = "count") + huaweicloud_dew_block.list_resource_instances(csms_params["resource_instances"],action=csms_params["action1"]) huaweicloud_dew_block.list_secret_tags(**csms_params) huaweicloud_dew_block.delete_secret_tag(**csms_params) @@ -258,25 +270,28 @@ def test_query_key_api_version_information(kms_params, huaweicloud_dew_block): if __name__ == "__main__": huaweicloud_dew_block = DewBlock.load("test-dew-block") - kms_params = kms_params(huaweicloud_dew_block, key_alias = "1-9") - kps_params = kps_params(huaweicloud_dew_block, name = "22-22") - test_key_lifecycle_management(kms_params, huaweicloud_dew_block) - test_key_pair_management(kps_params, huaweicloud_dew_block) - test_key_pair_task_management(kps_params, huaweicloud_dew_block) - test_data_key_management(kms_params, huaweicloud_dew_block) - test_key_grant_management(kms_params, huaweicloud_dew_block) - test_small_data_encryption(kms_params, huaweicloud_dew_block) - test_list_key(kms_params, huaweicloud_dew_block) - test_key_rotation_management(kms_params, huaweicloud_dew_block) - test_signature_verification(kms_params, huaweicloud_dew_block) - csms_params = csms_params(huaweicloud_dew_block, name = "demo", secret_string = "test_secret", secret_type = None, event_name = "demo_event") - test_lifecycle_management(csms_params, huaweicloud_dew_block) - test_credential_version_management(csms_params, huaweicloud_dew_block) - test_credential_version_status_management(csms_params, huaweicloud_dew_block) - test_voucher_label_management(csms_params, huaweicloud_dew_block) - test_event_management(csms_params, huaweicloud_dew_block) - test_key_label_management(kms_params, huaweicloud_dew_block) - test_query_key_api_version_information(kms_params, huaweicloud_dew_block) - + + # test_key_lifecycle_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_data_key_management(kms_params, huaweicloud_dew_block) + # test_small_data_encryption(kms_params, huaweicloud_dew_block) + # test_list_key(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_query_key_api_version_information(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_key_grant_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_signature_verification(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_key_label_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_key_rotation_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) + + + # test_key_pair_task_management(kps_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_key_pair_management(kps_params(huaweicloud_dew_block), huaweicloud_dew_block) + + # csms_params = csms_params(huaweicloud_dew_block, name = "demo", secret_string = "test_secret", secret_type = None, event_name = "demo_event") + # test_credential_version_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_lifecycle_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_credential_version_status_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_voucher_label_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) + # test_event_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) + + diff --git a/prefect_hwc.egg-info/SOURCES.txt b/prefect_hwc.egg-info/SOURCES.txt index 4592988..c919839 100644 --- a/prefect_hwc.egg-info/SOURCES.txt +++ b/prefect_hwc.egg-info/SOURCES.txt @@ -4,7 +4,6 @@ prefect_huaweicloud/__init__.py prefect_huaweicloud/dew_block.py prefect_huaweicloud/dew_client.py prefect_huaweicloud/obs_block.py -prefect_huaweicloud/test_dew.py prefect_huaweicloud/test/__init__.py prefect_huaweicloud/test/test_dew_block.py prefect_hwc.egg-info/PKG-INFO -- Gitee From b5dd7d03949bf5d3a5ce60ba9134cdb6aeffb097 Mon Sep 17 00:00:00 2001 From: Lky0312 <523175094@qq.com> Date: Mon, 26 Feb 2024 11:09:19 +0800 Subject: [PATCH 06/11] prefect-dew --- .idea/.gitignore | 3 - .idea/huaweicloud-prefect-block-python.iml | 10 - .idea/inspectionProfiles/Project_Default.xml | 6 - .../inspectionProfiles/profiles_settings.xml | 6 - .idea/misc.xml | 4 - .idea/modules.xml | 8 - .idea/vcs.xml | 6 - .vscode/settings.json | 6 - build/lib/prefect_huaweicloud/__init__.py | 6 - build/lib/prefect_huaweicloud/dew_block.py | 2274 ----------------- build/lib/prefect_huaweicloud/dew_client.py | 29 - build/lib/prefect_huaweicloud/obs_block.py | 364 --- .../lib/prefect_huaweicloud/test/__init__.py | 4 - .../test/test_dew_block.py | 297 --- build/lib/prefect_huaweicloud/test_dew.py | 111 - dist/prefect_hwc-0.1.0-py3.11.egg | Bin 42312 -> 0 bytes dist/prefect_hwc-0.1.0-py3.12.egg | Bin 43323 -> 0 bytes .../__pycache__/dew_block.cpython-311.pyc | Bin 134130 -> 0 bytes .../__pycache__/dew_block.cpython-312.pyc | Bin 130499 -> 0 bytes .../__pycache__/dew_client.cpython-311.pyc | Bin 2595 -> 0 bytes .../__pycache__/dew_client.cpython-312.pyc | Bin 2515 -> 0 bytes prefect_huaweicloud/dew_block.py | 4 +- prefect_huaweicloud/test/__init__.py | 4 - prefect_hwc.egg-info/PKG-INFO | 29 - prefect_hwc.egg-info/SOURCES.txt | 13 - prefect_hwc.egg-info/dependency_links.txt | 1 - prefect_hwc.egg-info/requires.txt | 3 - prefect_hwc.egg-info/top_level.txt | 1 - 28 files changed, 2 insertions(+), 3187 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/huaweicloud-prefect-block-python.iml delete mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 .idea/inspectionProfiles/profiles_settings.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml delete mode 100644 .vscode/settings.json delete mode 100644 build/lib/prefect_huaweicloud/__init__.py delete mode 100644 build/lib/prefect_huaweicloud/dew_block.py delete mode 100644 build/lib/prefect_huaweicloud/dew_client.py delete mode 100644 build/lib/prefect_huaweicloud/obs_block.py delete mode 100644 build/lib/prefect_huaweicloud/test/__init__.py delete mode 100644 build/lib/prefect_huaweicloud/test/test_dew_block.py delete mode 100644 build/lib/prefect_huaweicloud/test_dew.py delete mode 100644 dist/prefect_hwc-0.1.0-py3.11.egg delete mode 100644 dist/prefect_hwc-0.1.0-py3.12.egg delete mode 100644 prefect_huaweicloud/__pycache__/dew_block.cpython-311.pyc delete mode 100644 prefect_huaweicloud/__pycache__/dew_block.cpython-312.pyc delete mode 100644 prefect_huaweicloud/__pycache__/dew_client.cpython-311.pyc delete mode 100644 prefect_huaweicloud/__pycache__/dew_client.cpython-312.pyc delete mode 100644 prefect_huaweicloud/test/__init__.py delete mode 100644 prefect_hwc.egg-info/PKG-INFO delete mode 100644 prefect_hwc.egg-info/SOURCES.txt delete mode 100644 prefect_hwc.egg-info/dependency_links.txt delete mode 100644 prefect_hwc.egg-info/requires.txt delete mode 100644 prefect_hwc.egg-info/top_level.txt diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 359bb53..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# 默认忽略的文件 -/shelf/ -/workspace.xml diff --git a/.idea/huaweicloud-prefect-block-python.iml b/.idea/huaweicloud-prefect-block-python.iml deleted file mode 100644 index 74d515a..0000000 --- a/.idea/huaweicloud-prefect-block-python.iml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 85a34ff..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 6f57296..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 91203d5..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index a4f7a82..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "codecheck.ExcludeDirectory": "", - "codecheck.ScanDirectory": "", - "codecheck.allRule": true, - "codecheck.disabledRules": [] -} \ No newline at end of file diff --git a/build/lib/prefect_huaweicloud/__init__.py b/build/lib/prefect_huaweicloud/__init__.py deleted file mode 100644 index 6710c4a..0000000 --- a/build/lib/prefect_huaweicloud/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# ensure core blocks are registered - -from prefect_huaweicloud.obs_block import ObsBlock -from prefect_huaweicloud.dew_block import DewBlock -from prefect_huaweicloud.dew_client import DewClient -__all__ = ["ObsBlock","DewBlock","DewClient"] diff --git a/build/lib/prefect_huaweicloud/dew_block.py b/build/lib/prefect_huaweicloud/dew_block.py deleted file mode 100644 index 799a053..0000000 --- a/build/lib/prefect_huaweicloud/dew_block.py +++ /dev/null @@ -1,2274 +0,0 @@ -from typing import Optional, Dict, Any -from logging import Logger -from pydantic import Field, SecretStr -from prefect.blocks.abstract import Block -from prefect.logging.loggers import get_logger, get_run_logger -from prefect.exceptions import MissingContextError -from prefect import task -from pydantic import VERSION as PYDANTIC_VERSION -import json -if PYDANTIC_VERSION.startswith("2."): - from pydantic.v1 import Field -else: - from pydantic import Field -from dew_client import DewClient -from huaweicloudsdkkms.v2.model import * -from huaweicloudsdkcore.exceptions import exceptions -from huaweicloudsdkcsms.v1.model import * -from huaweicloudsdkkps.v3.model import * - - -class DewBlock(Block): - - _logo_url = "https://res-static.hc-cdn.cn/cloudbu-site/public/header-icon/Storage/OBS.png" # noqa - _block_type_name = "HuaweiCloud DEW" - _documentation_url = ("https://support.huaweicloud.com/intl/zh-cn/sdk-python-devg-obs/obs_22_0100.html") # noqa - - huawei_cloud_access_key_id: Optional[SecretStr] = Field( - default = None, - description = "A specific Huawei Cloud access key ID.", - title = "Huawei Cloud Access Key ID:", - ) - huawei_cloud_secret_access_key: Optional[SecretStr] = Field( - default = None, - description = "A specific Huawei Cloud secret access key.", - title = "Huawei Cloud Access Key Secret:", - ) - huawei_cloud_project_id: Optional[SecretStr] = Field( - default=None, - description = "A specific Huawei Cloud project id.", - title="Huawei Cloud project id", - ) - huawei_cloud_security_token: Optional[SecretStr] = Field( - default = None, - description = "SecurityToken in the temporary access key, " - "You can select a temporary token or AK/SK for authentication", - title = "Huawei Cloud Security Token", - ) - region_id:Optional[str] = Field( - default = None, - title = "region id", - ) - huawei_cloud_dew_parameters: Optional[Dict[str, Any]] = Field( - default=None, - description="Extra parameters for using dew.", - title="dew_parameters", - ) - def __init__(self, *args, **kwargs): - self.dew_client = DewClient(region_id = kwargs['region_id'], - ak = kwargs['huawei_cloud_access_key_id'], - sk = kwargs['huawei_cloud_secret_access_key'], - project_id = kwargs['huawei_cloud_project_id'] if kwargs.get('huawei_cloud_project_id') else None) - self.dew_parameters = kwargs['huawei_cloud_dew_parameters'] if kwargs.get('huawei_cloud_project_id') else None - @property - def logger(self) -> Logger: - """ - Returns a logger based on whether the ObjectStorageBlock - is called from within a flow or task run context. - If a run context is present, the logger property returns a run logger. - Else, it returns a default logger labeled with the class's name. - - Returns: - The run logger or a default logger with the class's name. - """ - try: - return get_run_logger() - except MissingContextError: - return get_logger(self.__class__.__name__) - - def create_key(self, key_alias = None, key_spec = None, key_usage = None, key_description = None, - origin = None, enterprise_project_id = None, sequence = None, keystore_id = None, **kwargs): - """ - Create a user master key, which can be a symmetric or asymmetric key. - - Args: - Key_ Alias: Non default master key alias, with a value range of 1 to 255 characters, satisfying - regular matching "^ [a-zA-Z0-9:/_ -] {1255} $", and not having the same name as the default - master key alias created by the system service. - type key_alias: str - """ - try: - request = CreateKeyRequest() - request.body = CreateKeyRequestBody( - key_alias = key_alias, - key_spec = key_spec, - key_usage = key_usage, - key_description = key_description, - origin = origin, - enterprise_project_id = enterprise_project_id, - sequence = sequence, - keystore_id = keystore_id - ) - response = self.dew_client.kms_client.create_key(request) - self.logger.debug("Created key") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def delete_key(self, key_id = None, pending_days = None, sequence = None, **kwargs): - """ - How many days do you plan to delete the key? The key can be deleted within 7-1096 days. - - Args: - key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str - :pending_days: How many days do you plan to delete the key, with values ranging from 7 to 1096. - :type pending_days: str - """ - try: - request = DeleteKeyRequest() - request.body = ScheduleKeyDeletionRequestBody( - key_id = key_id, - pending_days = pending_days, - sequence = sequence - ) - response = self.dew_client.kms_client.delete_key(request) - self.logger.debug("Successfully delete_key") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def disable_key(self, key_id = None, sequence = None, **kwargs): - """ - Disabled key, cannot be used after disabling the key. - - Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str - """ - try: - request = DisableKeyRequest() - request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence - ) - response = self.dew_client.kms_client.disable_key(request) - self.logger.info("Successfully disable_key:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def enable_key(self, key_id = None, sequence = None, **kwargs): - """ - Enable the key, which can only be used after it is enabled. - - Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str - """ - try: - request = EnableKeyRequest() - request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence - ) - response = self.dew_client.kms_client.enable_key(request) - self.logger.info("Successfully enable_key:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def update_key_Alias(self, key_id = None, key_alias = None, sequence = None, **kwargs): - """ - Modify the user master key alias - - Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str - :key_alias: Non default master key alias, ranging from 1 to 255 characters, satisfies regular matching - "^[a-zA-Z0-9:/_-]{1,255}$"and cannot have the suffix "/default". - :type key_alias: str - """ - try: - request = UpdateKeyAliasRequest() - request.body = UpdateKeyAliasRequestBody( - key_alias = key_alias, - key_id = key_id, - sequence = sequence - ) - response = self.dew_client.kms_client.update_key_alias(request) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def update_key_description(self, key_id = None, key_description = None, sequence = None, **kwargs): - """ - Modify user master key description information. - - Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str - :key_description: Key description, ranging from 0 to 255 characters. - :type key_description: str - """ - try: - request = UpdateKeyDescriptionRequest() - request.body = UpdateKeyDescriptionRequestBody( - key_id = key_id, - key_description = key_description, - sequence = sequence - ) - response = self.dew_client.kms_client.update_key_description(request) - self.logger.info("Successfully update_key_description:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def cancel_key_deletion(self, key_id = None, sequence = None, **kwargs): - """ - Cancel plan to delete key. - - Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str - """ - try: - request = CancelKeyDeletionRequest() - request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence - ) - response = self.dew_client.kms_client.cancel_key_deletion(request) - self.logger.info("Successfully canccel key daletion:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_data_key(self, key_id, key_spec = None, datakey_length = None, sequence = None, **kwargs): - """ - Create a data key and return a result containing both plaintext and ciphertext. - - Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str - """ - try: - request = CreateDatakeyRequest() - request.body = CreateDatakeyRequestBody( - key_id = key_id, - key_spec = key_spec, - datakey_length = datakey_length, - sequence = sequence - ) - response = self.dew_client.kms_client.create_datakey(request) - self.logger.info("Successfully created datakey:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_data_key_without_plaintext(self, key_id, key_spec = None, datakey_length = None, sequence = None, **kwargs): - """ - Create a data key and return a result that only contains ciphertext. - - Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str - """ - try: - request = CreateDatakeyWithoutPlaintextRequest() - request.body = CreateDatakeyRequestBody( - key_id = key_id, - key_spec = key_spec, - datakey_length = datakey_length, - sequence = sequence - ) - response = self.dew_client.kms_client.create_datakey_without_plaintext(request) - self.logger.info("Successfully created datakey without plaintext:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_random(self, random_data_length = None, sequence = None, **kwargs): - """ - Generate random numbers within the range of 8-8192 bits. - - Args: - :param random_ Data_ Length: The bit length of a random number. The value is a multiple of 8, with a range of 8 to 8192. - The bit length of a random number, with a value of 512. - :type random_ Data_ Length: str - """ - try: - request = CreateRandomRequest() - request.body = GenRandomRequestBody( - random_data_length = random_data_length, - sequence = sequence - ) - response = self.dew_client.kms_client.create_random(request) - self.logger.info("Successfully created random:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def decrypt_data_key(self, key_id = None, cipher_text = None, datakey_cipher_length = None, sequence = None, **kwargs): - """ - Decrypt data key, decrypt data key with specified master key. - - Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str - - :cipher_text: The hexadecimal string of DEK ciphertext and metadata. - The value is the cipher in the encrypted data key result_ The value of text. - :type cipher_text: str - - :datakey_cipher_length: The key byte length, with a range of 1 to 1024. Key byte length, with a value of "64". - :type datakey_cipher_length: str - """ - try: - request = DecryptDatakeyRequest() - request.body = DecryptDatakeyRequestBody( - key_id = key_id, - cipher_text = cipher_text, - datakey_cipher_length = datakey_cipher_length, - sequence = sequence - ) - response = self.dew_client.kms_client.decrypt_datakey(request) - self.logger.info("Successfully decrypted datakey:") - self.logger.info(response) - return response - - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def encrypt_data_key(self, key_id = None, plain_text = None, datakey_plain_length = None, sequence = None, **kwargs): - """ - Encrypt the data key with the specified master key. - - Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str - - :param plain_ Text: When CMK is AES, SHA256 (32 bytes) for DEK plaintext and DEK plaintext; When CMK is SM4, - both DEK plaintext and SM3 (32 bytes) of DEK plaintext are represented as hexadecimal strings. - :type plain_ Text: str - - :param datakey_ Plain_ Length: DEK plaintext byte length, with a range of 1 to 1024. DEK plaintext byte length, with a value of "64". - :type datakey_ Plain_ Length: str - """ - try: - request = EncryptDatakeyRequest() - request.body = EncryptDatakeyRequestBody( - key_id = key_id, - plain_text = plain_text, - datakey_plain_length = datakey_plain_length, - sequence = sequence - ) - response = self.dew_client.kms_client.encrypt_datakey(request) - self.logger.info("Successfully encrypted datakey:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_parameters_for_import(self, key_id,wrapping_algorithm = None, sequence = None, **kwargs): - """ - Obtain the necessary parameters for importing keys, including key import tokens and key encryption public keys. - - Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str - :wrapping_algorithm: Key material encryption algorithm, enumeration as follows: - RSAES_ OAEP_ SHA_ 256- SM2_ ENCRYPT, - some offices do not support this import type - :type wrapping_ algorithm: str - """ - try: - request = CreateParametersForImportRequest() - request.body = GetParametersForImportRequestBody( - key_id = key_id, - wrapping_algorithm = wrapping_algorithm, - sequence = sequence - ) - response = self.dew_client.kms_client.create_parameters_for_import(request) - self.logger.info("Successfully created parameters for import:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def delete_imported_key_material(self, key_id, sequence = None, **kwargs): - """ - Delete key material information. - - Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str - """ - try: - request = DeleteImportedKeyMaterialRequest() - request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence - ) - response = self.dew_client.kms_client.delete_imported_key_material(request) - self.logger.info("Successfully deleted imported key material:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def import_key_material(self, key_id = None, import_token = None, - encrypted_key_material = None, encrypted_privatekey = None, - expiration_time = None, sequence = None, **kwargs): - """ - Import key materials. - - Args: - : param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_id: str - - :param import_token: Key import token, in base64 format, that satisfies regular matching "^[0-9a-zA-Z+/=]{200,6144}$". - :type import_ Token: str - - :param encrypted_key_material: The encrypted symmetric key material, in base64 format, satisfies regular matching - "^[0-9a-zA-Z+/=]{344,360}$". If importing an asymmetric key, this parameter is the temporary intermediate key used to encrypt the private key. - :type encrypted_key_material: str - """ - try: - request = ImportKeyMaterialRequest() - request.body = ImportKeyMaterialRequestBody( - key_id = key_id, - import_token = import_token, - encrypted_key_material = encrypted_key_material, - encrypted_privatekey = encrypted_privatekey, - expiration_time = expiration_time, - sequence = sequence - ) - response = self.dew_client.kms_client.import_key_material(request) - self.logger.info("Successfully imported key material:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_grant(self, key_id = None, grantee_principal = None, listOperationsbody = None, - name = None, retiring_principal = None, grantee_principal_type = None, sequence = None, **kwargs): - """ - Create authorization, authorized users can operate on the authorization key. - - Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_id: str - - :param grantee_principal:Authorized user ID, 1~64 bytes, satisfies regular matching "^[a-zA-Z0-9]{1,64}$". - For example:0d0466b00d0466b00d0466b00d0466b0 - :type grantee_principal: str - - :param operations: List of authorized and allowed operations. Valid values: "create datakey", "create datakey without plaintext", - "encrypt datakey", "decrypt datakey", "describe key", "create grant", "retain grant", "encrypt data", "decrypt data". The valid - values cannot be just "create grant"- "Create datakey" Create data key - "Create datakey without plaintext" Create data key without - plaintext - "encrypt datakey" Encrypt data key - "decrypt datakey" Decrypt data key - "describe key" Query key information - - "retain grant" Retirement authorization - "encrypt data" Encrypt data - "decrypt data" Decrypt data - :type operations: list[str] - """ - try: - request = CreateGrantRequest() - request.body = CreateGrantRequestBody( - key_id = key_id, - grantee_principal = grantee_principal, - operations = listOperationsbody, - grantee_principal_type = grantee_principal_type, - retiring_principal = retiring_principal, - name = name, - sequence = sequence - ) - response = self.dew_client.kms_client.create_grant(request) - self.logger.info("Successfully create grant:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_retirable_grants(self, limit = None, marker = None, sequence = None, **kwargs): - """ - Query the list of authorizations that users can retire from. - """ - try: - request = ListRetirableGrantsRequest() - request.body = ListRetirableGrantsRequestBody( - limit = limit, - marker = marker, - sequence = sequence - ) - response = self.dew_client.kms_client.list_retirable_grants(request) - self.logger.info("Successfully list retirable grants:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_grants(self, key_id = None, limit = None, marker = None, sequence = None, **kwargs): - """ - Authorization list for querying keys - - Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_id: str - """ - try: - request = ListGrantsRequest() - request.body = ListGrantsRequestBody( - key_id = key_id, - limit = limit, - marker = marker, - sequence = sequence - ) - response = self.dew_client.kms_client.list_grants(request) - self.logger.info("Successfully list grants:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def cancel_self_grant(self, key_id = None, grant_id = None, sequence = None, **kwargs): - """ - Retirement authorization means that the authorized user no longer has the right to operate the authorization key. - For example, if user A authorizes user B to operate key A/key, and authorizes user C to revoke the authorization, - then users A, B, and C can all retire the authorization. After retiring the authorization, user B can no longer use key A. - - Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_id: str - - :param grant_id: Authorization ID, 64 bytes, satisfies regular matching "^[A-Fa-f0-9]{64}$". - For example:7c9a3286af4fcca5f0a385ad13e1d21a50e27b6dbcab50f37f30f93b8939827d - :type grant_id: str - """ - try: - request = CancelSelfGrantRequest() - request.body = RevokeGrantRequestBody( - grant_id = grant_id, - key_id = key_id, - sequence = sequence - ) - response = self.dew_client.kms_client.cancel_self_grant(request) - self.logger.info("Successfully cancel self grant:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def cancel_grant(self, key_id = None, grant_id = None, sequence = None, **kwargs): - """ - Revoke authorization, authorize the user to revoke the authorized user's permission to operate the key - - Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_id: str - - :param grant_id: Authorization ID, 64 bytes, satisfies regular matching "^[A-Fa-f0-9]{64}$". - For example:7c9a3286af4fcca5f0a385ad13e1d21a50e27b6dbcab50f37f30f93b8939827d - :type grant_id: str - """ - try: - request = CancelGrantRequest() - request.body = RevokeGrantRequestBody( - grant_id = grant_id, - key_id = key_id, - sequence = sequence - ) - response = self.dew_client.kms_client.cancel_grant(request) - self.logger.info("Successfully cancel grant:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def decrypt_data(self, cipher_text = None, encryption_algorithm = None, key_id = None, sequence = None, **kwargs): - """ - Decrypting data. - - Args: - :param cipher_text: Encrypted data ciphertext. The value is the cipher in the encrypted data result. - The value of text satisfies regular matching "^[0-9a-zA-Z+/=]{128,5648}$". - :type cipher_text: str - - """ - try: - request = DecryptDataRequest() - request.body = DecryptDataRequestBody( - cipher_text = cipher_text, - encryption_algorithm = encryption_algorithm, - key_id = key_id, - sequence = sequence - ) - response = self.dew_client.kms_client.decrypt_data(request) - self.logger.info("Successfully decrypted data:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def encrypt_data(self, key_id = None,plain_text = None, encryption_algorithm = None, sequence = None, **kwargs): - """ - Encrypt data using the specified user master key. - - Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_id: str - - :param plain_text: Clear text data, 1-4096 bytes, satisfies regular matching - "^.{14096}$", and the length range after converting to a byte array is 1-4096 bytes.. - :type plain_text: str - """ - try: - request = EncryptDataRequest() - request.body = EncryptDataRequestBody( - plain_text = plain_text, - key_id = key_id, - encryption_algorithm = encryption_algorithm, - sequence = sequence - ) - response = self.dew_client.kms_client.encrypt_data(request) - self.logger.info("Successfully encrypted data:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def sign(self, asymmetric_key_id = None, message = None, signing_algorithm = None, message_type = None, sequence = None, **kwargs): - """ - Digitally sign a message or message digest using a private key with an asymmetric key. - - Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_id: str - - :param signing_algorithm: The signature algorithm is listed as follows: - - RSASSA_PSS_SHA_256 - RSASSA_PSS_SHA_384 - RSASSA_PSS_SHA_512 - RSASSA_PKCS1_V1_5_SHA_256 - - RSASSA_PKCS1_V1_5_SHA_384 - RSASSA_PKCS1_V1_5_SHA_512 - ECDSA_SHA_256 - ECDSA_SHA_384 - - ECDSA_SHA_512 - SM2DSA_SM3 - :type signing_algorithm: str - - :param message: The message digest or message to be signed must have a message length of less than 4096 bytes and be encoded using Base64. - :type message: str - """ - try: - request = SignRequest() - request.body = SignRequestBody( - signing_algorithm = signing_algorithm, - message = message, - key_id = asymmetric_key_id, - message_type = message_type, - sequence = sequence - ) - response = self.dew_client.kms_client.sign(request) - self.logger.info("Successfully sign:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def validate_signature(self, asymmetric_key_id = None, message = None, signature = None, signing_algorithm = None, - message_type = None, sequence = None, **kwargs): - """ - Verify the signature of a message or message digest using a public key with an asymmetric key. - - Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_id: str - - :param signing_algorithm: The signature algorithm is listed as follows: - - RSASSA_PSS_SHA_256 - RSASSA_PSS_SHA_384 - RSASSA_PSS_SHA_512 - RSASSA_PKCS1_V1_5_SHA_256 - - RSASSA_PKCS1_V1_5_SHA_384 - RSASSA_PKCS1_V1_5_SHA_512 - ECDSA_SHA_256 - ECDSA_SHA_384 - - ECDSA_SHA_512 - SM2DSA_SM3 - :type signing_algorithm: str - - :param message: The message digest or message to be signed must have a message length of less than 4096 bytes and be encoded using Base64. - :type message: str - - :param signature: The signature value to be verified is encoded using Base64. - :type signature: str - """ - try: - request = ValidateSignatureRequest() - request.body = VerifyRequestBody( - key_id = asymmetric_key_id, - message = message, - signature = signature, - signing_algorithm = signing_algorithm, - message_type = message_type, - sequence = sequence - ) - response = self.dew_client.kms_client.validate_signature(request) - self.logger.info("Successfully list validate signature:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_key_detail(self, key_id = None,sequence = None, **kwargs): - """ - Query key details. - - Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_id: str - """ - try: - request = ListKeyDetailRequest() - request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence - ) - response = self.dew_client.kms_client.list_key_detail(request) - self.logger.info("Successfully list key detail:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_keys(self,limit = None, marker = None, key_state = None, key_spec = None, - enterprise_project_id = None, sequence = None, **kwargs): - """ - Query the list of all user keys. - """ - try: - request = ListKeysRequest() - request.body = ListKeysRequestBody( - limit = limit, - marker = marker, - key_state = key_state, - key_spec = key_spec, - enterprise_project_id = enterprise_project_id, - sequence = sequence - ) - response = self.dew_client.kms_client.list_keys(request) - self.logger.info(json.dumps(response.to_dict()).replace('}','}\n')) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def show_public_key(self, asymmetric_key_id = None, sequence = None, **kwargs): - """ - Query public key information for user specified asymmetric keys. - - Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_id: str - """ - try: - request = ShowPublicKeyRequest() - request.body = OperateKeyRequestBody( - key_id = asymmetric_key_id, - sequence = sequence - ) - response = self.dew_client.kms_client.show_public_key(request) - self.logger.info("Successfully show public key:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def show_user_instances(self, **kwargs): - """ - Query the number of instances to obtain the number of user master keys that have already been created by the user - """ - try: - request = ShowUserInstancesRequest() - response = self.dew_client.kms_client.show_user_instances(request) - self.logger.info("Successfully show user instances:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def show_user_quotas(self, **kwargs): - """ - Query quotas, query the total number of user master key quotas that users can create and current usage information. - """ - try: - request = ShowUserQuotasRequest() - response = self.dew_client.kms_client.show_user_quotas(request) - self.logger.info("Successfully show user quotas:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def show_version(self,version_id = None, **kwargs): - """ - Check the specified API version information - - Args: - :param version_id: API version number - :type version_id: str - """ - try: - request = ShowVersionRequest(version_id = version_id) - response = self.dew_client.kms_client.show_version(request) - self.logger.info("Successfully show_version:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def show_versions(self, **kwargs): - """ - Query API version information list. - """ - try: - request = ShowVersionsRequest() - response = self.dew_client.kms_client.show_versions(request) - self.logger.info("Successfully show versions:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(e) - - def disable_key_rotation(self, key_id = None, sequence = None, **kwargs): - """ - Turn off user master key rotation. - - Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_id: str - """ - try: - request = DisableKeyRotationRequest() - request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence - ) - response = self.dew_client.kms_client.disable_key_rotation(request) - self.logger.info("Successfully disable key rotation:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def enable_key_rotation(self, key_id = None, sequence = None, **kwargs): - """ - Enable user master key rotation. - - Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_id: str - """ - try: - request = EnableKeyRotationRequest() - request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence - ) - response = self.dew_client.kms_client.enable_key_rotation(request) - self.logger.info("Successfully enable key rotation:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def show_key_rotation_status(self, key_id = None, sequence = None, **kwargs): - """ - Query user master key rotation status - - Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_id: str - """ - try: - request = ShowKeyRotationStatusRequest() - request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence - ) - response = self.dew_client.kms_client.show_key_rotation_status(request) - self.logger.info("Successfully show key rotation status:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def update_key_rotation_interval(self, key_id = None, rotation_interval = None, sequence = None, **kwargs): - """ - Modify the user master key rotation cycle. - - Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". - For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_id: str - - :param rotation_interval: Rotation period, an integer with a range of values from 30 to 365. - The cycle range is set based on the frequency of key usage. If the frequency of key usage is high, - it is recommended to set it to a short cycle; On the contrary, set it to long cycle. - :type rotation_interval: int - """ - try: - request = UpdateKeyRotationIntervalRequest() - request.body = UpdateKeyRotationIntervalRequestBody( - rotation_interval = rotation_interval, - key_id = key_id, - sequence = sequence - ) - response = self.dew_client.kms_client.update_key_rotation_interval(request) - self.logger.info("Successfully update key rotation interval:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_keypair(self,name = None, type = None, public_key = None, scope = None, user_id = None, key_protection = None, **kwargs): - """ - Create and import SSH key pairs. - - Args: - :param name: The name of the SSH key pair.-The name of a newly created key pair cannot be the same as the name of an existing key pair. - - The SSH key pair name consists of English letters, numbers, underscores, and midlines, and the length cannot exceed 64 bytes - :type name: str - """ - try: - request = CreateKeypairRequest() - key_pair_body = CreateKeypairAction( - name = name, - type = type, - public_key = public_key, - scope = scope, - user_id = user_id, - key_protection = key_protection - ) - request.body = CreateKeypairRequestBody( - keypair = key_pair_body - ) - response = self.dew_client.kps_client.create_keypair(request) - self.logger.info("Successfully created keypair:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_keypairs(self,limit = None, marker = None, **kwargs): - """ - Query SSH key pair list. - """ - try: - request = ListKeypairsRequest(limit = limit, marker = marker) - response = self.dew_client.kps_client.list_keypairs(request) - self.logger.info("Successfully list keypairs:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def clear_private_key(self, keypair_name = None, **kwargs): - """ - Clear SSH key pair private key - - Args: - :param keypair_name: Key pair name. - :type keypair_name: str - """ - try: - request = ClearPrivateKeyRequest(keypair_name = keypair_name) - response = self.dew_client.kps_client.clear_private_key(request) - self.logger.info("Successfully cleared private key:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def import_private_key(self, user_id = None, name = None,type = None, kms_key_name = None, private_key = None, **kwargs): - """ - Import the private key into the specified key pair. - - Args: - :param name: The name of the SSH key pair.- The name of a newly created key pair cannot be the same as the name of an existing key pair. - - The SSH key pair name consists of English letters, numbers, underscores, and midlines, and the length cannot exceed 64 bytes - :type name: str - - :param private_key: Import the private key of an SSH key pair. - :type private_key: str - - :param type: 取值范围: "kms" or "default"- "Default" is the default encryption method, suitable for offices without KMS services. - - "KMS" refers to the use of KMS service encryption method. If the station does not have KMS service, please fill in "default". - :type type: str - - :param kms_key_name: The name of the KMS key.- If "type" is "kms", the kms service key name must be filled in. - :type kms_key_name: str - """ - try: - request = ImportPrivateKeyRequest() - encryption_key_protection = Encryption( - type = type, - kms_key_name = kms_key_name - ) - key_protection_keypair = ImportPrivateKeyProtection( - private_key = private_key, - encryption = encryption_key_protection - ) - key_pair_body = ImportPrivateKeyKeypairBean( - name = name, - key_protection = key_protection_keypair, - user_id = user_id - ) - request.body = ImportPrivateKeyRequestBody(keypair = key_pair_body) - response = self.dew_client.kps_client.import_private_key(request) - self.logger.info("Successfully import_private_key:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_keypair_detail(self, keypair_name = None, **kwargs): - """ - Query SSH key pair details - - Args: - :param keypair_name: Key pair name. - :type keypair_name: str - """ - try: - request = ListKeypairDetailRequest(keypair_name = keypair_name) - response = self.dew_client.kps_client.list_keypair_detail(request) - self.logger.info("Successfully list_keypair_detail") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_keypairs(self, **kwargs): - """ - Query SSH key pair list - """ - try: - request = ListKeypairsRequest() - response = self.dew_client.kps_client.list_keypairs(request) - self.logger.info("Successfully list private keys:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def update_keypair_description(self, keypair_name = None, description = None, **kwargs): - """ - Update SSH key pair description. - - Args: - :param keypair_name: Key pair name. - :type keypair_name: str - - :param description: Descriptive information - :type description: str - """ - try: - request = UpdateKeypairDescriptionRequest( - keypair_name = keypair_name - ) - key_pair_body = UpdateKeypairDescriptionReq( - description = description - ) - request.body = UpdateKeypairDescriptionRequestBody( - keypair = key_pair_body - ) - response = self.dew_client.kps_client.update_keypair_description(request) - self.logger.info("Successfully update keypair description:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def export_private_key(self, name = None, **kwargs): - """ - Export the private key of the specified key pair. - - :param name: SSH key pair name. - :type name: str - """ - try: - request = ExportPrivateKeyRequest() - key_pair_body = KeypairBean(name = name) - request.body = ExportPrivateKeyRequestBody(keypair = key_pair_body) - response = self.dew_client.kps_client.export_private_key(request) - self.logger.info("Successfully exported private key:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def delete_keypair(self, keypair_name = None, **kwargs): - """ - Delete SSH key pair. - - Args: - :param keypair_name: Key pair name. - :type keypair_name: str - """ - try: - request = DeleteKeypairRequest(keypair_name = keypair_name) - response = self.dew_client.kps_client.delete_keypair(request) - self.logger.info("Successfully deleted keypair") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def associate_keypair(self, keypair_name = None,type = None, key = None,id = None, disable_password = False, port = None, **kwargs): - """ - Bind a new SSH key pair to the specified virtual machine (replace or reset, replacement requires providing - the configured SSH key pair private key of the virtual machine; reset does not require providing the SSH key - pair private key of the virtual machine). - - Args: - :param keypair_name: Key pair name. - :type keypair_name: str - - :param id: Virtual machine id that needs to bind (replace or reset) SSH key pairs. - :type id: str - - :param type: The value is of enumeration type. password or keypair. - :type type: str - - :param key: - When type is the enumeration value password, key represents the password- When type is the enumeration - value keypair, key represents the private key. - :type key: str - """ - try: - request = AssociateKeypairRequest() - auth_server = Auth(type = type, key = key) - server_body = EcsServerInfo( - id = id, - auth = auth_server, - disable_password = disable_password, - port = port - ) - request.body = AssociateKeypairRequestBody( - server = server_body, - keypair_name = keypair_name - ) - response = self.dew_client.kps_client.associate_keypair(request) - self.logger.info("Successfully associate_keypair:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.info(id) - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def batch_associate_keypair(self, keypair_name = None, type = None, key = None, id = None, disable_password = None, port = None, **kwargs): - """ - Batch bind new SSH key pairs to the specified virtual machine. - - Args: - :param keypair_name: The name of the SSH key pair - :type keypair_name: list[str] - - :param id: List of virtual machine IDs that require binding (replacing or resetting) SSH key pairs. - :type id: list[str] - """ - try: - request = BatchAssociateKeypairRequest() - list_batch_keypairs_body = [] - if isinstance(keypair_name,list): - for s in range(len(keypair_name)): - auth_server = Auth( - type = type[s] if type is not None else None, - key = key[s] if key is not None else None - ) - server_satch_keypairs = EcsServerInfo( - id = id[s] if id is not None else None, - auth = auth_server, - disable_password = disable_password[s] if disable_password is not None else None, - port = port[s] if port is not None else None - ) - list_batch_keypairs_body.append(AssociateKeypairRequestBody( - keypair_name = keypair_name[s] if keypair_name is not None else None, - server = server_satch_keypairs - )) - else: - auth_server = Auth( - type = type, - key = key - ) - server_satch_keypairs = EcsServerInfo( - id = id, - auth = auth_server, - disable_password = disable_password, - port = port - ) - list_batch_keypairs_body.append(AssociateKeypairRequestBody( - keypair_name = keypair_name, - server = server_satch_keypairs - )) - - request.body = BatchAssociateKeypairRequestBody( - batch_keypairs = list_batch_keypairs_body - ) - response = self.dew_client.kps_client.batch_associate_keypair(request) - self.logger.info("Successfully batch_associate_keypair:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def delete_all_failed_task(self, **kwargs): - """ - Delete task information that failed the operation. - """ - try: - request = DeleteAllFailedTaskRequest() - response = self.dew_client.kps_client.delete_all_failed_task(request) - self.logger.info("Successfully delete_all_failed_task:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def delete_failed_task(self, task_id, **kwargs): - """ - Delete failed tasks. - - :param task_id: Task ID - :type task_id: str - """ - try: - request = DeleteFailedTaskRequest( - task_id = task_id, - ) - response = self.dew_client.kps_client.delete_failed_task(request) - self.logger.info("Successfully delete_failed_task:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def disassociate_keypair(self, id = None, type = None, key = None, **kwargs): - """ - Unbind SSH key pairs to the specified virtual machine and restore SSH password login. - :param id: Virtual machine ID that needs to bind (replace or reset) SSH key pairs - :type id: str - """ - try: - request = DisassociateKeypairRequest() - auth_server = Auth(type = type, key = key) - server_body = DisassociateEcsServerInfo(id = id, auth = auth_server) - request.body = DisassociateKeypairRequestBody(server = server_body) - response = self.dew_client.kps_client.disassociate_keypair(request) - self.logger.info("Successfully disassociate_keypair:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_failed_task(self, limit = None, offset = None, **kwargs): - """ - Query task information for failed binding, unbinding, and other operations. - """ - try: - request = ListFailedTaskRequest() - request.limit = limit - request.offset = offset - response = self.dew_client.kps_client.list_failed_task(request) - self.logger.info("Successfully list_failed_task:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_keypair_task(self, task_id = None, **kwargs): - """ - The task returned by the interface based on the SSH key_ ID, query the execution status of the SSH key for the current task. - - Args: - :param task_id: task ID - :type task_id: str - """ - try: - request = ListKeypairTaskRequest(task_id = task_id) - response = self.dew_client.kps_client.list_keypair_task(request) - self.logger.info("Successfully list_keypair_task:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_running_task(self, limit = None, offset = None, **kwargs): - """ - Query the task information being processed. - """ - try: - request = ListRunningTaskRequest() - request.limit = limit - request.offset = offset - response = self.dew_client.kps_client.list_running_task(request) - self.logger.info("Successfully list_running_task:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_secret(self, name = None, kms_key_id = None, description = None, - secret_binary = None, secret_string = None, secret_type = None, - auto_rotation = None, rotation_period = None, rotation_config = None, - event_subscriptions = None, enterprise_project_id = None, **kwargs): - """ - Create a new credential and store the credential value in the initial version of the credential. - The credential management service encrypts the credential values and stores them in the version under the credential object. - Each version can be associated with multiple credential version states, which are used to identify the stage in which the credential - version is in. A version without a version state marker is considered deprecated and can be automatically deleted using the credential - management service. - The initial version status is marked as SYSCURRENT. - - Args: - :param name: The name of the credential to be created. Constraint: The value range is 1 to 64 characters, satisfying the regular matching - "^[a-zA-Z0-9_-]{1,64}$". - :type name: str - """ - try: - request = CreateSecretRequest() - request.body = CreateSecretRequestBody( - secret_string = secret_string, - kms_key_id = kms_key_id, - name = name, - description = description, - secret_binary = secret_binary, - secret_type = secret_type, - auto_rotation = auto_rotation, - rotation_period = rotation_period, - rotation_config = rotation_config, - event_subscriptions = event_subscriptions, - enterprise_project_id = enterprise_project_id - ) - response = self.dew_client.cms_client.create_secret(request) - self.logger.info("Successfully create_secret:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def download_secret_blob(self, secret_name = None, **kwargs): - """ - Download backup files for specified credentials. - - Args: - :param secret_name: The name of the credential. - :type secret_name: str - """ - try: - request = DownloadSecretBlobRequest(secret_name = secret_name) - response = self.dew_client.cms_client.download_secret_blob(request) - self.logger.info("Successfully download_secret_blob:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_secrets(self, limit = None, marker = None, event_name = None, **kwargs): - """ - Query all credentials created by the current user under this project. - """ - try: - request = ListSecretsRequest() - request.limit = limit - request.marker = marker - request.event_name = event_name - response = self.dew_client.cms_client.list_secrets(request) - self.logger.info("Successfully list_secrets:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def show_secret(self, secret_name, **kwargs): - """ - Query information for specified credentials. - - Args: - :param secret_name: The name of the credential. - :type secret_name: str - """ - try: - request = ShowSecretRequest(secret_name = secret_name) - response = self.dew_client.cms_client.show_secret(request) - self.logger.info("Successfully show_secret:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def update_secret(self, kms_key_id = None, secret_name = None, description = None, - auto_rotation = None, rotation_period = None, listEventSubscriptionsbody = None, **kwargs): - """ - Update metadata information for specified credentials. - - Args: - :param secret_name: The name of the credential. - :type secret_name: str - """ - try: - request = UpdateSecretRequest() - request.body = UpdateSecretRequestBody( - event_subscriptions = listEventSubscriptionsbody, - description = description, - kms_key_id = kms_key_id, - auto_rotation = auto_rotation, - rotation_period = rotation_period, - ) - request.secret_name = secret_name - response = self.dew_client.cms_client.update_secret(request) - self.logger.info("Successfully update_secret:") - - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_secret_event(self, target_type = None, target_id = None, - target_name = None, event_name = None, state = None, - event_types = None, **kwargs): - """ - Create an event that can be configured on one or more credential objects. When an event is enabled and the - underlying event type is triggered on the credential object, the cloud service will send the corresponding - event notification to the notification subject specified by the event. - - Args: - :param name: The name of the newly created event notification. Constraint: The value range is 1 to 64 - characters, satisfying the regular matching "^ [a-zA-Z0-9_ -] {1,64} $". - :type name: str - - :param event_types:he basic event list for this event notification, with the following basic event types. - SECRET_ VERSION_ CREATED: Version Creation SECRET_ VERSION_ EXPIRED: Version expired SECRET_ ROTATED: credential - rotation SECRET_ DELETED: The credential deletion list cannot contain duplicate underlying event types. - :type event_types: list[str] - - :param state: controls whether an event takes effect. Only the enabled state can trigger the underlying event types - included.ENABLED: enable DisaBLED: disable - :type state: str - - :param target_ Type: The object type of the event notification. - :type target_ Type: str - - :param target_ ID: The object ID of the event notification. - :type target_ Id: str - - :param target_ Name: The name of the object notified by the event. - :type target_ Name: str - """ - try: - request = CreateSecretEventRequest() - notification_body = Notification( - target_type = target_type, - target_id = target_id, - target_name = target_name - ) - request.body = CreateSecretEventRequestBody( - notification = notification_body, - state = state, - event_types = event_types, - name = event_name, - ) - response = self.dew_client.cms_client.create_secret_event(request) - self.logger.info("Successfully create_secret_event:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def upload_secret_blob(self, secret_blob=None, **kwargs): - """ - Restore credential objects by uploading credential backup files. - - Args: - :param secret_blob: The credential backup file obtained by backing up the specified credential object contains - all current credential version information. The backup file is encrypted and encoded, and its content cannot be read directly. - :type secret_blob: str - """ - try: - request = UploadSecretBlobRequest() - request.body = UploadSecretBlobRequestBody(secret_blob = secret_blob) - response = self.dew_client.cms_client.upload_secret_blob(request) - self.logger.info("Successfully upload_secret_blob:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(e.status_code) - self.logger.error(e.request_id) - self.logger.error(e.error_code) - - def rotate_secret(self,secret_name = None, **kwargs): - """ - Immediately execute the rotation of credentials. Create a new credential version within the specified credentials to encrypt - and store randomly generated credential values in the background. At the same time, mark the newly created credential version - as SYSCURRENT status. - - Args: - :param secret_name: The name of the credential. - :type secret_name: str - """ - try: - request = RotateSecretRequest(secret_name = secret_name) - response = self.dew_client.cms_client.rotate_secret(request) - self.logger.info("Successfully rotate_secret:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def restore_secret(self,secret_name, **kwargs): - """ - Cancel the scheduled deletion task of credentials and restore the usable state of the credential object. - - Args: - :param secret_name: The name of the credential. - :type secret_name: str - """ - try: - request = RestoreSecretRequest(secret_name = secret_name) - response = self.dew_client.cms_client.restore_secret(request) - self.logger.info("Successfully restore_secret:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def delete_secret_for_schedule(self,recovery_window_in_days = None,secret_name = None, **kwargs): - """ - Specify a delayed deletion time, create a scheduled task to delete credentials, and set a delayed deletion time of 7-30 days. - - Args: - :param secret_name: The name of the credential. - :type secret_name: str - - :param recovery_ Window_ In_ Days: Create a task to delete credentials on a scheduled basis, and specify the number of days - that can be recovered. Constraints: 7-30. Default value: 30. - :type recovery_ Window_ In_ Days: int - """ - try: - request = DeleteSecretForScheduleRequest(secret_name = secret_name) - request.body = DeleteSecretForScheduleRequestBody( - recovery_window_in_days = recovery_window_in_days - ) - response = self.dew_client.cms_client.delete_secret_for_schedule(request) - self.logger.info("Successfully delete_secret_for_schedule:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def delete_secret(self,secret_name, **kwargs): - """ - Immediately delete the specified credentials and cannot recover them. - - Args: - :param secret_name: The name of the credential. - :type secret_name: str - """ - try: - request = DeleteSecretRequest(secret_name = secret_name) - response = self.dew_client.cms_client.delete_secret(request) - self.logger.info("Successfully delete_secret:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_secret_version(self,secret_name = None,secret_binary = None, - secret_string = None, version_stages = None, expire_time = None, **kwargs): - """ - Create a new credential version within the specified credentials to encrypt and store the new credential values. - By default, newly created credential versions are marked as SYSCURRENT, while the previous credential version marked - with SYSCURRENT is marked as SYSPREVIOUS. You can override the default behavior by specifying the Version Stage parameter. - - Args: - :param secret_name: The name of the credential. - :type secret_name: str - """ - try: - request = CreateSecretVersionRequest(secret_name=secret_name) - request.body = CreateSecretVersionRequestBody( - secret_string = secret_string, - secret_binary = secret_binary, - version_stages = version_stages, - expire_time = expire_time - ) - response = self.dew_client.cms_client.create_secret_version(request) - self.logger.info("Successfully create_secret_version:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_secret_versions(self,secret_name = None, marker = None, limit = None, **kwargs): - """ - Query version list information under specified credentials. - - Args: - :param secret_name: The name of the credential. - :type secret_name: str - """ - try: - request = ListSecretVersionsRequest() - request.secret_name = secret_name - request.marker = marker - request.limit = limit - response = self.dew_client.cms_client.list_secret_versions(request) - self.logger.info("Successfully list_secret_versions:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def show_secret_version(self,secret_name = None,version_id = None, **kwargs): - """ - Query the information of the specified credential version and the plaintext credential value in the version, - only the credentials with ENABLED status can be queried. The latest version of the credentials can be accessed - through/v1/{project_id}/secrets/{secretname}/versions/latest (i.e. assigning {version _id} in the current interface URL as latest) - - Args: - :param secret_name: The name of the credential. - :type secret_name: str - - :param version_id: The version identifier of the credential. - :type version_id: str - """ - try: - request = ShowSecretVersionRequest() - request.secret_name = secret_name - request.version_id = version_id - response = self.dew_client.cms_client.show_secret_version(request) - self.logger.info("Successfully show_secret_version:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def update_version(self,secret_name = None, version_id = None, expire_time = None, **kwargs): - """ - Currently, it supports updating the validity period of specified credential versions, and can only update - credentials with ENABLED status. When the event associated with the subscription includes a basic event type - of "version expiration", only one event notification will be triggered after each version expiration update. - - Args: - :param secret_name: The name of the credential. - :type secret_name: str - - :param version_id: The version identifier of the credential. - :type version_id: str - - :param expire_time: The expiration time of the credential version, timestamp, is the total number of seconds - from January 1, 1970 to that time. The default is empty, and the value used to determine the validity period - when subscribing to the "version expiration" event type for credentials. - :type expire_time: int - """ - try: - request = UpdateVersionRequest() - request.version_id = version_id - request.secret_name = secret_name - request.body = UpdateVersionRequestBody( - expire_time = expire_time - ) - response = self.dew_client.cms_client.update_version(request) - self.logger.info("Successfully update_version:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def show_secret_stage(self, secret_name=None, stage_name=None, **kwargs): - """ - Query the version information of the specified credential version status marker. - - Args: - :param secret_name: The name of the credential. - :type secret_name: str - - :param stage_name: The name of the credential version status. - :type stage_name: str - """ - try: - request = ShowSecretStageRequest(secret_name=secret_name,stage_name=stage_name) - response = self.dew_client.cms_client.show_secret_stage(request) - self.logger.info("Successfully show_secret_stage:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def update_secret_stage(self, secret_name = None, stage_name = None, version_id = None, **kwargs): - """ - Update the version status of credentials. - - Args: - :param secret_name: The name of the credential. - :type secret_name: str - - :param stage_name: The name of the credential version status.matching '^[a-zA-Z0-9_-]{1,64}$' - :type stage_name: str - """ - try: - request = UpdateSecretStageRequest(secret_name = secret_name, stage_name = stage_name) - request.body = UpdateSecretStageRequestBody(version_id = version_id) - response = self.dew_client.cms_client.update_secret_stage(request) - self.logger.info("Successfully update_secret_stage:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def delete_secret_stage(self, secret_name = None, stage_name = None, **kwargs): - """ - Delete the version status of credentials. - - Args: - :param secret_name: The name of the credential. - :type secret_name: str - - :param stage_name: The name of the credential version status. - :type stage_name: str - """ - try: - request = DeleteSecretStageRequest(secret_name = secret_name, stage_name = stage_name) - response = self.dew_client.cms_client.delete_secret_stage(request) - self.logger.info("Successfully delete_secret_stage:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def batch_create_or_delete_tags(self, secret_id = None, key = None, value = None, action = None, sequence = None, **kwargs): - """ - Batch add or remove credential labels. - - Args: - :param secret_id: Credential ID - :type secret_id: str - - :param key: The name of the tag. A label key can only correspond to one label value for the same credential; - Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: - The value range is from 1 to 128 characters, which satisfies regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L} - \\\\p{Z}\\\\p{N}_.:=+\\\\-@]*)(?<!\\\\s)$\" - :type key: list[str] - - :param action: Operation identifier: limited to "create" and "delete" only. - :type action: str - """ - try: - request = BatchCreateOrDeleteTagsRequest(secret_id = secret_id) - - - listTagsbody = [] - if isinstance(key,list): - for s in range(len(key)): - listTagsbody.append(TagItem(key =key[s], - value = value[s] if value is not None else None)) - else: - listTagsbody.append(TagItem(key =key, value = value)) - - request.body = BatchCreateOrDeleteTagsRequestBody( - action=action, - tags=listTagsbody, - sequence=sequence - ) - response = self.dew_client.cms_client.batch_create_or_delete_tags(request) - self.logger.info("Successfully batch_create_or_delete_tags:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_secret_tag(self, secret_id = None, key = None, value = None, **kwargs): - """ - Add credential labels. - - Args: - :param secret_id: Credential ID - :type secret_id: str - - :param key: The name of the tag. A label key can only correspond to one label value for the same credential; - Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: - The value range is from 1 to 128 characters, which satisfies regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L} - \\\\p{Z}\\\\p{N}_.:=+\\\\-@]*)(?<!\\\\s)$\" - :type key: str - """ - try: - request = CreateSecretTagRequest(secret_id = secret_id) - tagbody = TagItem( - key = key, - value = value, - ) - request.body = CreateSecretTagRequestBody( - tag=tagbody - ) - response = self.dew_client.cms_client.create_secret_tag(request) - self.logger.info("Successfully create_secret_tag:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def delete_secret_tag(self, secret_id = None, key = None, **kwargs): - """ - Delete credential labels. - - Args: - :param secret_id: Credential ID - :type secret_id: str - - :param key: The name of the tag. A label key can only correspond to one label value for the same credential; - Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: - The value range is from 1 to 128 characters, which satisfies regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L} - \\\\p{Z}\\\\p{N}_.:=+\\\\-@]*)(?<!\\\\s)$\" - :type key: str - """ - try: - request = DeleteSecretTagRequest(secret_id = secret_id, key = key) - response = self.dew_client.cms_client.delete_secret_tag(request) - self.logger.info("Successfully delete_secret_tag:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_project_secrets_tags(self,**kwargs): - """ - Query the collection of all credential labels for the user under the specified project. - """ - try: - request = ListProjectSecretsTagsRequest() - response = self.dew_client.cms_client.list_project_secrets_tags(request) - self.logger.info("Successfully list_project_secrets_tags:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_resource_instances(self,resource_instances = None, values = None, key = None, limit = None, offset=None, action = None, matches = None, sequence = None, **kwargs): - """ - Query credential instances. Filter user credentials through tag filtering and return a list of credentials. - - Args: - :param action: Operation identifier (can be set as "filter" or "count")- Filter: represents filtering - - Count: represents the total number of queries. - :type action: str - - :param resource_instances: Set the value to resource_instances. - :type resource_instances: str - """ - try: - request = ListResourceInstancesRequest(resource_instances = resource_instances) - listTagsbody = [] - if isinstance(key,list): - for s in range(len(key)): - listTagsbody.append(Tag(key = key[s] if key is not None else None, - values = values[s] if values is not None else None)) - else: - listTagsbody.append(Tag(key = key, values = values)) - request.body = ListResourceInstancesRequestBody( - tags = listTagsbody if key is not None else None, - action = action, - matches = matches, - sequence = sequence, - offset = offset, - limit = limit - ) - response = self.dew_client.cms_client.list_resource_instances(request) - self.logger.info("Successfully list_resource_instances:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_secret_tags(self, secret_id = None, **kwargs): - """ - Query credential labels. - - Args: - :param secret_id: Credential ID - :type secret_id: str - """ - try: - request = ListSecretTagsRequest(secret_id = secret_id) - response = self.dew_client.cms_client.list_secret_tags(request) - self.logger.info("Successfully list_secret_tags:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def delete_secret_event(self, event_name = None, **kwargs): - """ - Immediately delete the specified event and cannot be restored. If there is a credential reference in the event, - it cannot be deleted. Please dissociate it first. - - Args: - :param event_name: The name of the event notification. - :type event_name: str - """ - try: - request = DeleteSecretEventRequest(event_name = event_name) - response = self.dew_client.cms_client.delete_secret_event(request) - self.logger.info("Successfully delete_secret_event:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_secret_events(self, marker = None, limit = None, **kwargs): - """ - Query all events created by the current user under this project - """ - try: - request = ListSecretEventsRequest() - request.limit =limit - request.marker = marker - response = self.dew_client.cms_client.list_secret_events(request) - self.logger.info("Successfully list_secret_events:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def show_secret_event(self, event_name = None, **kwargs): - """ - Query information for a specified event. - - Args: - :param event_name: The name of the event notification. - :type event_name: str - """ - try: - request = ShowSecretEventRequest(event_name = event_name) - response = self.dew_client.cms_client.show_secret_event(request) - self.logger.info("Successfully show_secret_event:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def update_secret_event(self, event_name = None, state = None, event_types = None, notification = None, **kwargs): - """ - Update metadata information for specified events. The metadata that supports updates includes event enable status, - basic type list, and notification topic. - - Args: - :param event_name: The name of the event notification. - :type event_name: str - """ - try: - request = UpdateSecretEventRequest(event_name = event_name) - request.body = UpdateSecretEventRequestBody( - state = state, - event_types = event_types, - notification = notification - ) - response = self.dew_client.cms_client.update_secret_event(request) - self.logger.info("Successfully update_secret_event:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_notification_records(self, marker = None, limit = None, **kwargs): - """ - Query triggered event notification records. - """ - try: - request = ListNotificationRecordsRequest( - limit = limit, - marker = marker - ) - response = self.dew_client.cms_client.list_notification_records(request) - self.logger.info("Successfully list_notification_records:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def batch_create_kms_tags(self, key_id = None, key = None, value = None, action = None, **kwargs): - """ - - Args: - :param key_id: key ID - :type key_id: str - - :param action: Operation identifier: limited to "create" and "delete". - :type action: str - - :param key: The name of the label. A label key can only correspond to one label value for the same credential; - Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: - Value range from 1 to 128 characters, satisfying regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L}\\\\p{Z}\\\\p{N} - _.:=+\\\\-@]*)(?<!\\\\s)$\" - :type key: list[str] - """ - try: - request = BatchCreateKmsTagsRequest(key_id = key_id) - listTagsbody = [] - if isinstance(key,list): - for s in range(len(key)): - listTagsbody.append(TagItem(key =key[s], - value = value[s] if value is not None else None)) - else: - listTagsbody.append(TagItem(key =key, value = value)) - request.body = BatchCreateKmsTagsRequestBody( - action=action, - tags=listTagsbody - ) - response = self.dew_client.kms_client.batch_create_kms_tags(request) - self.logger.info("Successfully batch_create_kms_tags:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_kms_tag(self, key_id = None, key = None, value = None, **kwargs): - """ - Add key labels. - - Args: - :param key_id: key ID - :type key_id: str - - :param key: The name of the label. A label key can only correspond to one label value for the same credential; - Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: - Value range from 1 to 128 characters, satisfying regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L}\\\\p{Z}\\\\p{N} - _.:=+\\\\-@]*)(?<!\\\\s)$\" - :type key: str - """ - try: - request = CreateKmsTagRequest(key_id = key_id) - tagbody = TagItem( - key = key, - value = value - ) - request.body = CreateKmsTagRequestBody( - tag=tagbody - ) - response = self.dew_client.kms_client.create_kms_tag(request) - self.logger.info("Successfully create_kms_tag:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_kms_tags(self, **kwargs): - """ - Query all label collections of the user under the specified project. - """ - try: - request = ListKmsTagsRequest() - response = self.dew_client.kms_client.list_kms_tags(request) - self.logger.info("Successfully list_kms_tags:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def delete_tag(self, key_id = None, key = None, **kwargs): - """ - Delete key label. - - Args: - :param key_id: Key ID - :type key_id: str - :param key: Value of label key - :type key: str - """ - try: - request = DeleteTagRequest(key_id = key_id, key = key) - response = self.dew_client.kms_client.delete_tag(request) - self.logger.info("Successfully delete_tag:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_kms_by_tags(self,key = None, values = None, limit=None, offset=None, action=None, tags=None, matches=None, sequence=None, **kwargs): - """ - Query key instances. Filter through tags to query detailed information about the specified user's master key. - """ - try: - request = ListKmsByTagsRequest(resource_instances = "resource_instances") - listTagsbody = [] - if isinstance(key,list): - for s in range(len(key)): - listTagsbody.append(Tag(key = key[s] if key is not None else None, - values = values[s] if values is not None else None)) - else: - listTagsbody.append(Tag(key = key, values = values)) - request.body = ListKmsByTagsRequestBody( - tags = listTagsbody if key is not None else None, - action = action, - offset = offset, - limit = limit, - sequence = sequence, - matches = matches - ) - response = self.dew_client.kms_client.list_kms_by_tags(request) - self.logger.info("Successfully list_kms_by_tags:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_kms_tags(self, key_id = None, **kwargs): - """ - Query the key label. - - Args: - :param key_id: Key ID - :type key_id: str - """ - try: - request = ShowKmsTagsRequest(key_id = key_id) - response = self.dew_client.kms_client.show_kms_tags(request) - self.logger.info("Successfully show_kms_tags:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - - def create_key_store(self, keystore_alias = None, hsm_cluster_id = None, hsm_ca_cert = None, **kwargs): - """" - Create a tenant exclusive key repository that uses DHSM instances as key storage. - - Args: - :param keystore_alias: Exclusive key repository alias, with a value range of 1 to 255 characters, satisfies regular matching - "^[a-zA-Z0-9:/_-]{1,255}$", and does not have the same name as existing exclusive key repository aliases. - :type keystore_alias: str - :param hsm_cluster_id: The DHSM cluster ID requires that the cluster has not yet created a dedicated key repository. - :type hsm_cluster_id: str - :param hsm_ca_cert: CA certificate for DHSM cluster - :type hsm_ca_cert: str - """ - try: - request = CreateKeyStoreRequest() - request.body = CreateKeyStoreRequestBody( - hsm_ca_cert = hsm_ca_cert, - hsm_cluster_id = hsm_cluster_id, - keystore_alias = keystore_alias - ) - response = self.dew_client.kms_client.create_key_store(request) - self.logger.info("Successfully create_key_store:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") \ No newline at end of file diff --git a/build/lib/prefect_huaweicloud/dew_client.py b/build/lib/prefect_huaweicloud/dew_client.py deleted file mode 100644 index b933607..0000000 --- a/build/lib/prefect_huaweicloud/dew_client.py +++ /dev/null @@ -1,29 +0,0 @@ -from huaweicloudsdkcore.auth.credentials import BasicCredentials -from huaweicloudsdkkms.v2.region.kms_region import KmsRegion -from huaweicloudsdkkms.v2 import KmsClient -from huaweicloudsdkkps.v3.region.kps_region import KpsRegion -from huaweicloudsdkkps.v3 import KpsClient -from huaweicloudsdkcsms.v1.region.csms_region import CsmsRegion -from huaweicloudsdkcsms.v1 import CsmsClient - - -class DewClient(): - def __init__(self,region_id = None, ak = None, sk = None, project_id = None, *args, **kwargs): - if not ak or not sk: - raise Exception("please input both huawei_cloud_access_key_id and huawei_cloud_secret_access_key") - self.region_id = region_id - self.__ak = ak - self.__sk = sk - self.__project_id=project_id - self.kms_client = KmsClient.new_builder() \ - .with_credentials(BasicCredentials(self.__ak, self.__sk, self.__project_id)) \ - .with_region(KmsRegion.value_of(self.region_id)) \ - .build() - self.kps_client = KpsClient.new_builder() \ - .with_credentials(BasicCredentials(self.__ak, self.__sk, self.__project_id)) \ - .with_region(KpsRegion.value_of(self.region_id)) \ - .build() - self.cms_client = CsmsClient.new_builder() \ - .with_credentials(BasicCredentials(self.__ak, self.__sk, self.__project_id)) \ - .with_region(CsmsRegion.value_of(self.region_id)) \ - .build() diff --git a/build/lib/prefect_huaweicloud/obs_block.py b/build/lib/prefect_huaweicloud/obs_block.py deleted file mode 100644 index bea8e36..0000000 --- a/build/lib/prefect_huaweicloud/obs_block.py +++ /dev/null @@ -1,364 +0,0 @@ -import io -import json -import os -from logging import Logger -from typing import Optional -from pathlib import Path - -from obs import ObsClient - -from prefect.blocks.core import Block -from prefect.filesystems import WritableDeploymentStorage, WritableFileSystem -from pydantic import Field, SecretStr - -from prefect.utilities.asyncutils import sync_compatible, run_sync_in_worker_thread -from prefect.utilities.filesystem import filter_files -from prefect.logging.loggers import get_logger, get_run_logger -from prefect.exceptions import MissingContextError - - -class ObsBlock(WritableFileSystem, WritableDeploymentStorage, Block): - - - _logo_url = "https://res-static.hc-cdn.cn/cloudbu-site/public/header-icon/Storage/OBS.png" # noqa - _block_type_name = "HuaweiCloud Obs" - _documentation_url = ("https://support.huaweicloud.com/intl/zh-cn/sdk-python-devg-obs/obs_22_0100.html") # noqa - - huawei_cloud_access_key_id: Optional[SecretStr] = Field( - default=None, - description="A specific Huawei Cloud access key ID.", - title="Huawei Cloud Access Key ID", - ) - huawei_cloud_secret_access_key: Optional[SecretStr] = Field( - default=None, - description="A specific Huawei Cloud secret access key.", - title="Huawei Cloud Access Key Secret", - ) - huawei_cloud_security_token: Optional[SecretStr] = Field( - default=None, - description="SecurityToken in the temporary access key, " - "You can select a temporary token or AK/SK for authentication", - title="Huawei Cloud Security Token", - ) - end_point: str = Field( - default="https://obs.cn-south-1.myhuaweicloud.com", - description=( - "Service address for connecting to OBS. The value can contain the protocol type, domain name, " - "and port number. Example: https://your-endpoint:443. (For security purposes, HTTPS is recommended.)" - ), - title="End Point", - ) - bucket: str = Field( - default=None, - description=( - "Name of the bucket for creating a bucket client" - ), - title="Bucket", - ) - - prefix: Optional[str] = Field( - default=None, - description=( - "Name prefix that the objects to be listed must contain. example: xxx/xxx. prefix cannot start with /" - ), - title="Prefix", - ) - - extra_params: Optional[str] = Field( - default='{}', - description=( - "Additional parameters such as max_retry_count," - " max_redirect_count, and ssl_verify are written in JSON format," - " as shown in {'max_retry_count': 3,'max_redirect_count': 2}." - "Detailed link: https://support.huaweicloud.com/intl/en-us/sdk-python-devg-obs/obs_22_0601.html" - ), - title="Extra Params", - ) - - @property - def logger(self) -> Logger: - """ - Returns a logger based on whether the ObjectStorageBlock - is called from within a flow or task run context. - If a run context is present, the logger property returns a run logger. - Else, it returns a default logger labeled with the class's name. - - Returns: - The run logger or a default logger with the class's name. - """ - try: - return get_run_logger() - except MissingContextError: - return get_logger(self.__class__.__name__) - - @sync_compatible - async def read_path(self, path: str) -> bytes: - """ - Reading OBS File Objects - Args: - path: OBS File Object Key - - Returns: OBS File BytesIO - - """ - path = self._resolve_path(path) - return await run_sync_in_worker_thread(self._download_file_object, path) - - @sync_compatible - async def write_path(self, path: str, content: bytes) -> None: - """ - Writing a File Object to OBS - Args: - path: OBS Storage Path - content: File Object Flow - Returns: - - """ - path = self._resolve_path(path) - - await run_sync_in_worker_thread(self._upload_file_object, path, content) - - return path - - @sync_compatible - async def get_directory( - self, from_path: str = None, local_path: str = None - ) -> None: - """ - Download all files from the folder path in the OBS bucket to the local path. - Args: - from_path: obs dir path - local_path: local dir path - - Returns: - - """ - - folder_path = self.prefix if not self.prefix == "/" else None - if from_path is None: - from_path = str(folder_path) if folder_path else None - - if local_path is None: - local_path = str(Path("..").absolute()) - else: - local_path = str(Path(local_path).expanduser()) - obs_client = self._get_obs_client() - for path, is_dir in self._bucket_list_object(from_path): - self.logger.info(path) - target_path = os.path.join( - local_path, - path - ) - target_path = os.path.normpath(target_path) - if is_dir: - os.makedirs(target_path, exist_ok=True) - continue - try: - resp = obs_client.getObject(self.bucket, path, downloadPath=target_path) - if resp.status < 300: - self.logger.info('requestId: %s', resp.requestId) - else: - self.logger.error('errorCode: %s', resp.errorCode) - self.logger.error('errorMessage: %s', resp.errorMessage) - except Exception as e: - import traceback - self.logger.error(traceback.format_exc()) - - @sync_compatible - async def put_directory( - self, local_path: str = None, to_path: str = None, ignore_file: str = None - ) -> int: - """ - Pushes all files in the local folder to the specified folder in the OBS bucket. - - Args: - local_path: Path to local directory to upload from. - to_path: Path in OBS bucket to upload to. Defaults to block's configured - basepath. - ignore_file: Path to file containing gitignore style expressions for - filepaths to ignore. - Returns: - - """ - - if local_path is None: - raise Exception("local_path can't be None") - - local_path = os.path.normpath(local_path) - included_files = None - if ignore_file: - with open(ignore_file, "r") as f: - ignore_patterns = f.readlines() - - included_files = filter_files(local_path, ignore_patterns) - - uploaded_file_count = 0 - for local_file_path in Path(local_path).expanduser().rglob("*"): - if ( - included_files is not None - and str(local_file_path.relative_to(local_path)) not in included_files - ): - continue - elif not local_file_path.is_dir(): - remote_file_path = Path(to_path) / local_file_path.relative_to( - local_path - ) - with open(local_file_path, "rb") as local_file: - local_file_content = local_file.read() - - await self.write_path( - path=remote_file_path.as_posix(), content=local_file_content - ) - uploaded_file_count += 1 - - return uploaded_file_count - - def _get_obs_client(self) -> ObsClient: - """ - The authenticated OBS client is returned. You can select a temporary token or AK/SK for authentication. - Returns: ObsClient - """ - extra_params = json.loads(self.extra_params) - - if self.huawei_cloud_security_token: - return ObsClient( - security_token=self.huawei_cloud_security_token.get_secret_value(), - server=self.end_point, - **extra_params - ) - if not self.huawei_cloud_access_key_id or not self.huawei_cloud_secret_access_key: - raise Exception("please input both huawei_cloud_access_key_id and huawei_cloud_secret_access_key") - - return ObsClient( - access_key_id=self.huawei_cloud_access_key_id.get_secret_value(), - secret_access_key=self.huawei_cloud_secret_access_key.get_secret_value(), - server=self.end_point, - **extra_params - ) - - def _resolve_path(self, path): - """ - Concatenate the file object path based on the preset path prefix. - - Args: - path: Path before splicing - - Returns: Path after splicing - - """ - - path = ( - (Path(self.prefix) / path).as_posix() if self.prefix else path - ) - - return path - - def _download_file_object_inner(self, obs_client, key, stream): - resp = obs_client.getObject(self.bucket, key, loadStreamInMemory=False) - - if resp.status < 300: - self.logger.info('requestId: %s', resp.requestId) - # 读取对象内容 - while True: - chunk = resp.body.response.read(65536) - if not chunk: - break - stream.write(chunk) - resp.body.response.close() - else: - self.logger.error('errorCode: %s', resp.errorCode) - self.logger.error('errorMessage: %s', resp.errorMessage) - - def _download_file_object(self, key: str): - """ - Downloading a File Object from OBS - - Args: - key: OBS File Object Key - - Returns: OBS File BytesIO - - """ - obs_client = self._get_obs_client() - with io.BytesIO() as stream: - try: - self._download_file_object_inner(obs_client, key, stream) - except Exception as e: - import traceback - self.logger.error(traceback.format_exc()) - stream.seek(0) - output = stream.read() - obs_client.close() - return output - - def _upload_file_object(self, path: str, data: bytes) -> None: - """ - Uploading a File Object to OBS - Args: - path: OBS Storage Path - data: File Object Flow - - Returns: - - """ - obs_client = self._get_obs_client() - try: - - resp = obs_client.putContent(self.bucket, path, content=data) - - if resp.status < 300: - self.logger.info('requestId: %s', resp.requestId) - else: - self.logger.error('errorCode: %s', resp.errorCode) - self.logger.error('errorMessage: %s', resp.errorMessage) - except Exception as e: - import traceback - self.logger.error(traceback.format_exc()) - - def _bucket_list_object_inner(self, obs_client, prefix, mark, max_num): - object_list = [] - resp = obs_client.listObjects(self.bucket, prefix=prefix, marker=mark, max_keys=max_num) - self.logger.info(resp) - if resp.status < 300: - self.logger.info('requestId: %s', resp.requestId) - index = 1 - for content in resp.body.contents: - self.logger.info('object [%s]', str(index)) - index += 1 - if content.size == 0: - object_list.append((content.key, True)) - else: - object_list.append((content.key, False)) - if resp.body.is_truncated is True: - return object_list, False, resp.body.next_marker - else: - return object_list, True, resp.body.next_marker - else: - self.logger.error('errorCode: %s', resp.errorCode) - self.logger.error('errorMessage: %s', resp.errorMessage) - return [], True, False - - def _bucket_list_object(self, prefix): - """ - Querying All Objects in a Bucket - Args: - prefix: Path Prefix - - Returns: file object key and is dir bool - - """ - obs_client = self._get_obs_client() - max_num = 1000 - mark = None - all_object_list = [] - is_break = False - try: - while not is_break: - object_list, is_break, mark = self._bucket_list_object_inner(obs_client, prefix, mark, max_num) - all_object_list.extend(object_list) - except Exception as e: - import traceback - self.logger.error(traceback.format_exc()) - finally: - obs_client.close() - return all_object_list diff --git a/build/lib/prefect_huaweicloud/test/__init__.py b/build/lib/prefect_huaweicloud/test/__init__.py deleted file mode 100644 index 92f0816..0000000 --- a/build/lib/prefect_huaweicloud/test/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from prefect_huaweicloud.obs_block import ObsBlock -from prefect_huaweicloud.dew_block import DewBlock -from prefect_huaweicloud.dew_client import DewClient -__all__ = ["ObsBlock","DewBlock","DewClient"] \ No newline at end of file diff --git a/build/lib/prefect_huaweicloud/test/test_dew_block.py b/build/lib/prefect_huaweicloud/test/test_dew_block.py deleted file mode 100644 index bf90810..0000000 --- a/build/lib/prefect_huaweicloud/test/test_dew_block.py +++ /dev/null @@ -1,297 +0,0 @@ -import sys -from pathlib import Path -sys.path.append(str(Path(__file__).resolve().parents[1])) -from dew_block import DewBlock -from prefect import flow,task -def kms_params(huaweicloud_dew_block): - test_key = None - key_alias = None - if "key_alias" in huaweicloud_dew_block.dew_parameters: - key_alias = huaweicloud_dew_block.dew_parameters["key_alias"] - test_key = huaweicloud_dew_block.create_key(key_alias = key_alias) - return dict( - key_alias = key_alias if key_alias is not None else None, - key_id = test_key.key_info.key_id if test_key is not None else None, - key_description = None, - pending_days = huaweicloud_dew_block.dew_parameters["pending_days"] if "pending_days" in huaweicloud_dew_block.dew_parameters else None, - - random_data_length = huaweicloud_dew_block.dew_parameters["random_data_length"] if "random_data_length" in huaweicloud_dew_block.dew_parameters else None, - datakey_length = huaweicloud_dew_block.dew_parameters["datakey_length"] if "datakey_length" in huaweicloud_dew_block.dew_parameters else None, - datakey_plain_length = huaweicloud_dew_block.dew_parameters["datakey_plain_length"] if "datakey_plain_length" in huaweicloud_dew_block.dew_parameters else None, - datakey_cipher_length = huaweicloud_dew_block.dew_parameters["datakey_cipher_length"] if "datakey_cipher_length" in huaweicloud_dew_block.dew_parameters else None, - cipher_text = None, - plain_text = None, - datakey_dgst = None, - - asymmetric_key_id=huaweicloud_dew_block.dew_parameters["asymmetric_key_id"] if "asymmetric_key_id" in huaweicloud_dew_block.dew_parameters else None, - - grantee_principal = huaweicloud_dew_block.dew_parameters["grantee_principal"] if "grantee_principal" in huaweicloud_dew_block.dew_parameters else None, - listOperationsbody = huaweicloud_dew_block.dew_parameters["listOperationsbody"] if "listOperationsbody" in huaweicloud_dew_block.dew_parameters else None, - grant_id = None, - - rotation_interval = huaweicloud_dew_block.dew_parameters["rotation_interval"] if "rotation_interval" in huaweicloud_dew_block.dew_parameters else None, - - signing_algorithm = huaweicloud_dew_block.dew_parameters["signing_algorithm"] if "signing_algorithm" in huaweicloud_dew_block.dew_parameters else None, - message = huaweicloud_dew_block.dew_parameters["message"] if "message" in huaweicloud_dew_block.dew_parameters else None, - message_type = huaweicloud_dew_block.dew_parameters["message_type"] if "message_type" in huaweicloud_dew_block.dew_parameters else None, - signature = None, - - action = huaweicloud_dew_block.dew_parameters["action"] if "action" in huaweicloud_dew_block.dew_parameters else None, - key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, - version_id = huaweicloud_dew_block.dew_parameters["version_id"] if "version_id" in huaweicloud_dew_block.dew_parameters else None, - ) - - -def kps_params(huaweicloud_dew_block): - key_pair_list = huaweicloud_dew_block.list_keypairs() - test_key = None - name = None - if "name" in huaweicloud_dew_block.dew_parameters: - name = huaweicloud_dew_block.dew_parameters["name"] - if name in list(x.keypair.name for x in key_pair_list.keypairs[:]): - huaweicloud_dew_block.delete_keypair(keypair_name = name) - test_key = huaweicloud_dew_block.create_keypair(name = name) - return dict( - name = name, - keypair_name = name, - private_key = test_key.keypair.private_key, - description = None, - id = huaweicloud_dew_block.dew_parameters["id"] if "id" in huaweicloud_dew_block.dew_parameters else None, - kms_key_name = huaweicloud_dew_block.dew_parameters["kms_key_name"] if "kms_key_name" in huaweicloud_dew_block.dew_parameters else None, - type = huaweicloud_dew_block.dew_parameters["type"] if "type" in huaweicloud_dew_block.dew_parameters else None, - key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, - task_id = None, - disable_password = huaweicloud_dew_block.dew_parameters["disable_password"] if "disable_password" in huaweicloud_dew_block.dew_parameters else None, - ) - - -def csms_params(huaweicloud_dew_block): - secret_list = huaweicloud_dew_block.list_secrets() - secret_string = None - event_name = None - test_secret = None - if "name" and "secret_string" in huaweicloud_dew_block.dew_parameters: - name = huaweicloud_dew_block.dew_parameters["name"] - secret_string = huaweicloud_dew_block.dew_parameters["secret_string"] - - if name in list(x.name for x in secret_list.secrets[:]): - huaweicloud_dew_block.delete_secret(secret_name = name) - test_secret = huaweicloud_dew_block.create_secret(name,secret_string = secret_string) - - secret_event = huaweicloud_dew_block.list_secret_events() - - if event_name in list(x.name for x in secret_event.events[:]): - huaweicloud_dew_block.delete_secret_event(event_name = event_name) - return dict( - secret_name = test_secret.secret.name, - version_id = huaweicloud_dew_block.dew_parameters["version_id"] if "version_id" in huaweicloud_dew_block.dew_parameters else None, - secret_blob = None, - expire_time = huaweicloud_dew_block.dew_parameters["expire_time"] if "expire_time" in huaweicloud_dew_block.dew_parameters else None, - secret_string = secret_string, - stage_name = huaweicloud_dew_block.dew_parameters["stage_name"] if "stage_name" in huaweicloud_dew_block.dew_parameters else None, - update_stage_name=huaweicloud_dew_block.dew_parameters["update_stage_name"] if "update_stage_name" in huaweicloud_dew_block.dew_parameters else None, - update_version_id = huaweicloud_dew_block.dew_parameters["update_version_id"] if "update_version_id" in huaweicloud_dew_block.dew_parameters else None, - secret_id = test_secret.secret.id, - key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, - action = huaweicloud_dew_block.dew_parameters["action0"] if "action0" in huaweicloud_dew_block.dew_parameters else None, - action1=huaweicloud_dew_block.dew_parameters["action1"] if "action1" in huaweicloud_dew_block.dew_parameters else None, - - value = huaweicloud_dew_block.dew_parameters["value"] if "value" in huaweicloud_dew_block.dew_parameters else None, - values = huaweicloud_dew_block.dew_parameters["values"] if "values" in huaweicloud_dew_block.dew_parameters else None, - resource_instances = huaweicloud_dew_block.dew_parameters["resource_instances"] if "resource_instances" in huaweicloud_dew_block.dew_parameters else None, - event_name = huaweicloud_dew_block.dew_parameters["event_name"] if "event_name" in huaweicloud_dew_block.dew_parameters else None, - event_types = huaweicloud_dew_block.dew_parameters["event_types"] if "event_types" in huaweicloud_dew_block.dew_parameters else None, - state = huaweicloud_dew_block.dew_parameters["state"] if "state" in huaweicloud_dew_block.dew_parameters else None, - target_type = huaweicloud_dew_block.dew_parameters["target_type"] if "target_type" in huaweicloud_dew_block.dew_parameters else None, - target_id = huaweicloud_dew_block.dew_parameters["target_id"] if "target_id" in huaweicloud_dew_block.dew_parameters else None, - target_name = huaweicloud_dew_block.dew_parameters["target_name"] if "target_name" in huaweicloud_dew_block.dew_parameters else None, - recovery_window_in_days = huaweicloud_dew_block.dew_parameters["recovery_window_in_days"] if "recovery_window_in_days" in huaweicloud_dew_block.dew_parameters else None, - - ) - -@flow -def test_key_lifecycle_management(kms_params, huaweicloud_dew_block): - row_key_alias = kms_params['key_alias'] - huaweicloud_dew_block.create_key(**kms_params) - huaweicloud_dew_block.disable_key(**kms_params) - huaweicloud_dew_block.enable_key(**kms_params) - kms_params['key_alias'] = "test_alias" - huaweicloud_dew_block.update_key_Alias(**kms_params) - kms_params['key_alias'] = row_key_alias - huaweicloud_dew_block.update_key_Alias(**kms_params) - kms_params['key_description'] = "test_update_description" - huaweicloud_dew_block.update_key_description(**kms_params) - huaweicloud_dew_block.delete_key(**kms_params) - huaweicloud_dew_block.cancel_key_deletion(**kms_params) - huaweicloud_dew_block.enable_key(**kms_params) - - -@flow -def test_data_key_management(kms_params, huaweicloud_dew_block): - huaweicloud_dew_block.create_data_key_without_plaintext(**kms_params) - create_data_key_response = huaweicloud_dew_block.create_data_key(**kms_params) - huaweicloud_dew_block.create_random(**kms_params) - kms_params["cipher_text"] = create_data_key_response.cipher_text - decrypt_data_key_response = huaweicloud_dew_block.decrypt_data_key(**kms_params) - kms_params["datakey_dgst"] = decrypt_data_key_response.datakey_dgst - kms_params["plain_text"] = decrypt_data_key_response.data_key+decrypt_data_key_response.datakey_dgst - huaweicloud_dew_block.encrypt_data_key(**kms_params) - - -@flow -def test_key_grant_management(kms_params, huaweicloud_dew_block): - create_grant_response = huaweicloud_dew_block.create_grant(**kms_params) - kms_params["grant_id"] = create_grant_response.grant_id - huaweicloud_dew_block.list_retirable_grants(**kms_params) - huaweicloud_dew_block.cancel_self_grant(**kms_params) - huaweicloud_dew_block.create_grant(**kms_params) - huaweicloud_dew_block.cancel_grant(**kms_params) - huaweicloud_dew_block.list_grants(**kms_params) - - -@flow -def test_key_pair_management(kps_params, huaweicloud_dew_block): - huaweicloud_dew_block.import_private_key(**kps_params) - huaweicloud_dew_block.export_private_key(**kps_params) - huaweicloud_dew_block.list_keypair_detail(**kps_params) - huaweicloud_dew_block.list_keypairs(**kps_params) - huaweicloud_dew_block.clear_private_key(**kps_params) - - kps_params['description'] = "test_update_description" - huaweicloud_dew_block.update_keypair_description(**kps_params) - - huaweicloud_dew_block.delete_keypair(**kps_params) - -@flow -def test_key_pair_task_management(kps_params, huaweicloud_dew_block): - kps_params["task_id"] = huaweicloud_dew_block.associate_keypair(**kps_params).task_id - huaweicloud_dew_block.batch_associate_keypair(**kps_params) - # huaweicloud_dew_block.delete_failed_task(**kps_params) - huaweicloud_dew_block.delete_all_failed_task(**kps_params) - huaweicloud_dew_block.disassociate_keypair(**kps_params) - huaweicloud_dew_block.list_failed_task(**kps_params) - huaweicloud_dew_block.list_keypair_task(**kps_params) - huaweicloud_dew_block.list_running_task(**kps_params) - -@flow -def test_small_data_encryption(kms_params, huaweicloud_dew_block): - encrypt_data_response = huaweicloud_dew_block.encrypt_data(**kms_params) - kms_params["cipher_text"] = encrypt_data_response.cipher_text - huaweicloud_dew_block.decrypt_data(**kms_params) - - - -@flow -def test_list_key(kms_params, huaweicloud_dew_block): - huaweicloud_dew_block.list_keys(**kms_params) - huaweicloud_dew_block.list_key_detail(**kms_params) - huaweicloud_dew_block.show_public_key(**kms_params) - huaweicloud_dew_block.show_user_instances(**kms_params) - huaweicloud_dew_block.show_user_quotas(**kms_params) - - -@flow -def test_key_rotation_management(kms_params, huaweicloud_dew_block): - huaweicloud_dew_block.enable_key_rotation(**kms_params) - huaweicloud_dew_block.show_key_rotation_status(**kms_params) - huaweicloud_dew_block.update_key_rotation_interval(**kms_params) - huaweicloud_dew_block.disable_key_rotation(**kms_params) - - -@flow -def test_signature_verification(kms_params, huaweicloud_dew_block): - kms_params["key_id"] = "95afc13e-a5ed-4271-b8e9-a71079e8c6b3" - row_sign = huaweicloud_dew_block.sign(**kms_params) - kms_params['signature'] = row_sign.signature - huaweicloud_dew_block.validate_signature(**kms_params) - - -@flow -def test_lifecycle_management(csms_params, huaweicloud_dew_block): - huaweicloud_dew_block.show_secret(**csms_params) - csms_params["secret_blob"] = huaweicloud_dew_block.download_secret_blob(**csms_params).secret_blob - huaweicloud_dew_block.update_secret(**csms_params) - huaweicloud_dew_block.delete_secret_for_schedule(**csms_params) - huaweicloud_dew_block.restore_secret(**csms_params) - huaweicloud_dew_block.delete_secret(**csms_params) - huaweicloud_dew_block.upload_secret_blob(**csms_params) - - -@flow -def test_credential_version_management(csms_params, huaweicloud_dew_block): - huaweicloud_dew_block.create_secret_version(**csms_params) - huaweicloud_dew_block.show_secret_version(**csms_params) - huaweicloud_dew_block.list_secret_versions(**csms_params) - huaweicloud_dew_block.update_version(**csms_params) - - -@flow -def test_credential_version_status_management(csms_params, huaweicloud_dew_block): - show_secret_stage_response = huaweicloud_dew_block.show_secret_stage(**csms_params) - csms_params["stage_name"] = csms_params["update_stage_name"] - csms_params["version_id"] = show_secret_stage_response.stage.version_id - huaweicloud_dew_block.update_secret_stage(**csms_params) - huaweicloud_dew_block.delete_secret_stage(**csms_params) - - -@flow -def test_voucher_label_management(csms_params, huaweicloud_dew_block): - huaweicloud_dew_block.batch_create_or_delete_tags(**csms_params) - huaweicloud_dew_block.create_secret_tag(**csms_params) - huaweicloud_dew_block.list_project_secrets_tags(**csms_params) - huaweicloud_dew_block.list_resource_instances(csms_params["resource_instances"],action=csms_params["action1"]) - huaweicloud_dew_block.list_secret_tags(**csms_params) - huaweicloud_dew_block.delete_secret_tag(**csms_params) - - -@flow -def test_event_management(csms_params, huaweicloud_dew_block): - huaweicloud_dew_block.create_secret_event(**csms_params) - huaweicloud_dew_block.show_secret_event(**csms_params) - huaweicloud_dew_block.update_secret_event(**csms_params) - huaweicloud_dew_block.delete_secret_event(**csms_params) - huaweicloud_dew_block.list_notification_records(**csms_params) - - -@flow -def test_key_label_management(kms_params, huaweicloud_dew_block): - huaweicloud_dew_block.list_kms_tags(**kms_params) - huaweicloud_dew_block.batch_create_kms_tags(**kms_params) - huaweicloud_dew_block.create_kms_tag(**kms_params) - huaweicloud_dew_block.list_kms_by_tags(action = "count") - huaweicloud_dew_block.show_kms_tags(**kms_params) - huaweicloud_dew_block.delete_tag(**kms_params) - -@flow -def test_query_key_api_version_information(kms_params, huaweicloud_dew_block): - huaweicloud_dew_block.show_versions(**kms_params) - huaweicloud_dew_block.show_version(**kms_params) - - -if __name__ == "__main__": - huaweicloud_dew_block = DewBlock.load("test-dew-block") - - # test_key_lifecycle_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_data_key_management(kms_params, huaweicloud_dew_block) - # test_small_data_encryption(kms_params, huaweicloud_dew_block) - # test_list_key(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_query_key_api_version_information(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_key_grant_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_signature_verification(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_key_label_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_key_rotation_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) - - - # test_key_pair_task_management(kps_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_key_pair_management(kps_params(huaweicloud_dew_block), huaweicloud_dew_block) - - # csms_params = csms_params(huaweicloud_dew_block, name = "demo", secret_string = "test_secret", secret_type = None, event_name = "demo_event") - # test_credential_version_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_lifecycle_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_credential_version_status_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_voucher_label_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_event_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) - - - - diff --git a/build/lib/prefect_huaweicloud/test_dew.py b/build/lib/prefect_huaweicloud/test_dew.py deleted file mode 100644 index 10bfa6e..0000000 --- a/build/lib/prefect_huaweicloud/test_dew.py +++ /dev/null @@ -1,111 +0,0 @@ -from prefect_huaweicloud.dew_block import DewBlock - -from prefect import flow,task - -def kms_params(huaweicloud_dew_block,key_alias=None): - test_key=huaweicloud_dew_block.create_key(key_alias=key_alias) - return dict( - key_alias=key_alias, - key_id=test_key.key_info.key_id, - key_description=None, - pending_days=7, - random_data_length=512, - datakey_length=512, - datakey_plain_length=64, - datakey_cipher_length=64, - cipher_text=None, - plain_text=None, - datakey_dgst=None, - - grantee_principal="0f9eaeef3b7347f3804c2b27d126273e", - listOperationsbody = [ - "describe-key", - "create-datakey", - "encrypt-datakey"], - grant_id=None, - encryption_algorithm="SYMMETRIC_DEFAULT" - ) - - -def kps_params(huaweicloud_dew_block,name): - key_pair_list=huaweicloud_dew_block.list_keypairs() - if name in list(x.keypair.name for x in key_pair_list.keypairs[:]): - huaweicloud_dew_block.delete_keypair(keypair_name=name) - test_key=huaweicloud_dew_block.create_keypair(name=name) - return dict( - name=name, - keypair_name=name, - private_key=test_key.keypair.private_key, - # key_id=test_key.keypair.user_id, - description=None - ) - -@flow -def test_key_lifecycle_management(kms_params,huaweicloud_dew_block): - row_key_alias=kms_params['key_alias'] - huaweicloud_dew_block.create_key(**kms_params) - huaweicloud_dew_block.disable_key(**kms_params) - huaweicloud_dew_block.enable_key(**kms_params) - kms_params['key_alias']="test_alias" - huaweicloud_dew_block.update_key_Alias(**kms_params) - kms_params['key_alias']=row_key_alias - huaweicloud_dew_block.update_key_Alias(**kms_params) - kms_params['key_description']="test_update_description" - huaweicloud_dew_block.update_key_description(**kms_params) - huaweicloud_dew_block.delete_key(**kms_params) - huaweicloud_dew_block.cancel_key_deletion(**kms_params) - huaweicloud_dew_block.enable_key(**kms_params) - -@flow -def test_data_key_management(kms_params,huaweicloud_dew_block): - huaweicloud_dew_block.create_data_key_without_plaintext(**kms_params) - create_data_key_response=huaweicloud_dew_block.create_data_key(**kms_params) - huaweicloud_dew_block.create_random(**kms_params) - kms_params["cipher_text"]=create_data_key_response.cipher_text - decrypt_data_key_response=huaweicloud_dew_block.decrypt_data_key(**kms_params) - kms_params["datakey_dgst"]=decrypt_data_key_response.datakey_dgst - kms_params["plain_text"]=decrypt_data_key_response.data_key+decrypt_data_key_response.datakey_dgst - huaweicloud_dew_block.encrypt_data_key(**kms_params) - - -@flow -def test_key_grant_management(kms_params,huaweicloud_dew_block): - create_grant_response=huaweicloud_dew_block.create_grant(**kms_params) - kms_params["grant_id"]=create_grant_response.grant_id - huaweicloud_dew_block.list_retirable_grants(**kms_params) - # huaweicloud_dew_block.cancel_self_grant(**kms_params) - huaweicloud_dew_block.cancel_grant(**kms_params) - huaweicloud_dew_block.list_grants(**kms_params) - - - - - -@flow -def test_key_pair_management(kps_params,huaweicloud_dew_block): - row_keypair_name=kps_params['name'] - huaweicloud_dew_block.import_private_key(**kps_params) - huaweicloud_dew_block.export_private_key(**kps_params) - huaweicloud_dew_block.list_keypair_detail(**kps_params) - huaweicloud_dew_block.clear_private_key(**kps_params) - - kps_params['description']="test_update_description" - huaweicloud_dew_block.update_keypair_description(**kps_params) - - huaweicloud_dew_block.delete_keypair(**kps_params) - -def test_small_data_encryption(kms_params,huaweicloud_dew_block): - encrypt_data_response=huaweicloud_dew_block.encrypt_data(**kms_params) - kms_params["cipher_text"]=encrypt_data_response.cipher_text - huaweicloud_dew_block.decrypt_data(**kms_params) - - -if __name__=="__main__": - huaweicloud_dew_block = DewBlock.load("test-dew-block") - kms_params=kms_params(huaweicloud_dew_block,key_alias="12-26") -# test_key_lifecycle_management(kms_params,huaweicloud_dew_block) -# test_key_pair_management(kps_params(huaweicloud_dew_block,name="22-22"),huaweicloud_dew_block) - test_data_key_management(kms_params,huaweicloud_dew_block) -# test_key_grant_management(kms_params,huaweicloud_dew_block) - test_small_data_encryption(kms_params,huaweicloud_dew_block) - \ No newline at end of file diff --git a/dist/prefect_hwc-0.1.0-py3.11.egg b/dist/prefect_hwc-0.1.0-py3.11.egg deleted file mode 100644 index 1241b50da91171daa12f1d5ed8ba5e85b53c7000..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42312 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 J?%n;n{{b}s!AAf9 diff --git a/dist/prefect_hwc-0.1.0-py3.12.egg b/dist/prefect_hwc-0.1.0-py3.12.egg deleted file mode 100644 index 8bf54a6cbd6f7e25a0b23384b640890dfb6df0a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43323 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℘-!v}b-Ee@<18}0i!<{AOLc}pZ=MgOBt}7~ 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 diff --git a/prefect_huaweicloud/__pycache__/dew_block.cpython-312.pyc b/prefect_huaweicloud/__pycache__/dew_block.cpython-312.pyc deleted file mode 100644 index 7d72f963e03259307faa1e769b9712e40de37293..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130499 zcmeFa3wRV)eka;etMzP2fItn1M*4B_v1Eyv zOlEhT-PxU)wNj{{r%55b?Q{rDba0XgN^EgDs|PVb55PA^ZUR5=eH^=%LCYqxBg>d*>?&8KcXMj z77~BFTU-zbd^Hdc#0ye^!Gd!IgN5e`2ZQH=1$3@3RWukn7h-=0Q^kWN=Sl`k&y}*@ zMX9pE@^j_v?@+2@FnlgNSb46J{Vq;b4OXA4W`CEY77Q*tw~+l^iaHjZt6_har52xC zTo_2y3~aJGWgp|^SI{ro%o6mYB2`Om7X*fi*)P@;R!cY)8C-g9Df_!Jwd|J**crU<;%sGVCH++xI2?#qe<2WGkSMCZ7dulj#5f{rZBr-iI zRy12hf19I2;x~%b98adx$)O7!!$X|X8I>w)Y@8ygAJ3QJ~1Bt-7f_UIu;Zu0Q z=YsLVb4Bssxe$iEI9?PF#f!gHB8Q+PQJN@QhFTKk@zO_e6s5}Ixthe{__D;3zQXwOFBDzjRR_-1mIcZJ@pQcI3kByQ@l1RLj!WaC@s&6( z!*Lak%W-}+j&(R1IIh6?H8`%s?|K|p;kXvZ)i}QnMYrFa8=J;MGTi*Lf;>rvBY95>+3MjSWdcN2~cI5y+B3Fo)qxEaT-I5x(| z<1IKgiTbwT?`E{N9mg%=+z$M`73X&1*b?7`k=PdBjs14?W)IHoi0{R(ohZ?YU%PPJ zhvRM>AH{JGTHcT2Ui9_=j;%O<5XXJE`!O6JMGx9=+>hVwI39?1ptgM|)rnsRakdM` z$8bD^V_W>?_+cE|QQPA98ckR7RM*!Pow;4)czU# z>W)8yUuW3eUq6A?`*4incmc;=l@ry^<#a5trNj%XP9ZhAj74bwmW+oX}W3ZFzW#R06TiFZ=kefr|e;nb^rw;ySrTGjDN(SIndyKTP6j_;zSK(-h>-KaU__+aRD(qO!s z!S1UdMfN9Su@l{awSkO$+3NykeL)~&v153J1I4)2wGGgR=-RALDpvSRpgV9W@KW%Z zz@>tQf+#gvj<>7=dFPQn6jQDks0wd64OD1kt%@Gu z`x{A^nK6TpC-s%?;#ckJx>D&xqmj%g#RPI&kCuw|0-EBikF0@MDw2dHh=HX&uX z$qLK@>b`3mAY5{7@xm(tlnZF?=qyBm0*=W;vThqC% zO?z9n^cYRg885e>x=CYQeWMW_iW@`28KXb?B9$h-Cyg1(zyc4;PFNjwH018R0pT9w z88>>zcr9ZX&_S?C=8MS~aL2+2I%dX35;W93?73TwbjFm|8%ncf@=~^x{v`gEpBznt zyUteANtI149yXH~l0(@g0M&#!VkXmx9-E$LOVf!LMiWD^M79EVrop2ph+(SWUqGCC z@_rTZ`lIQd*l;{y>^I)8Zp2XHu5<=P=|p3r`UKv;6QrAvw^ub9{KR1T0`5N1upqmD zH+M8KcA8h5UF<&7J{%v*7WHCpuEm#~Ex$O39x=WnTh7Oq*lx3#E{5WX-q8!$qT~=5 zO`6@=TCVgE)puDck8Fr_C0n69Vz%6VI%r2^-?L@1+YOZrqRp+S+H9fSHrj2c9l^1= zlXkmkx0`nBvCEc-YO|#vaU;V+=|r|5k*>rg$A~e+Hy^|4@fr#D_5+^8h4k-ZN07g$ z?CFBHYu8WLZhYnN+jU!JS3ELXx0d$xEwjs3&u-jLKUX!px3FwQ)hma;cHevu`>$P?UV7-2$7jO}zI61bkKPHdoC>deb#Nx!D9@~z3a@ze zGc)1!vo&?EoCIxIcBgvlRQ1-s4iusTvKZa?TGi_>e0%bZ$=8Rk_1t>$t@A%Tf9u3M zfr4iX8fP1uzJ2VCW3L~$w(3^FTNOX7xIPIwwEAqp-v$aQpDy?@+yDJLL8|ioH1VOI zZ#&Rl5V%oL)6o>XvAC_eV`K2<#t?qQh>5Z`NvM9$pHPL|gbL&-$Sar#-81qOx*`b8 zWU&t+xOe2K*lG(ztvE;WRN~VsJ$WkeB~K;3N}fjln@XM@ z2V*%H9U3#@(Xq45-VxotyU$5nS|xQcj^JTb+CmuAI+7TQgVgoVxV9R346~rmj5=c=K%R+WGI?M( zy%ZW`U00k9s{Mf+S%P>7WFA3H?`Z2Kv8OQY4_iJg{`dS3moe&)$i&OhsDmL>`@rJbLZv=}4Cg`fsn= zJrmv|LH*;${&zX{?`?ZD@aCg60R0=)!2Y$tn`=Y(5fiwL=jH+m6H;dUvA@WP{Xl*p zT2B<+Gvt@ro5_$5#(ps5*W5KBsSJ=m#E^dh8w>0Pq=;gj2?Us6;zy5`*yXIhAea;n zkp9fIF~OwRhbBPi^PvgFxS|zVJc3E_h3DjCmEpk?87m6W2YD4Fe zlhDRMp0Q8q5VL~62n8~8M9Viy6twgOO0s7PpyW9DG(F#9$uTRfzk)02-^LC=xhTwl za>I0O1F_6o2`GV*p`bv?QWt}KU~1`sYnP^%9#&A2Ao2FfJu~6G_a7zqwCxMLxv!>U zL-0lwP_jOFvp$3$^C+qC#}5NaKB1yy*ARiE#R98Jo8cj_OHRCmz7%TL1iK~vaAKv! za7jgrd4|AbsRJze2+fI=3;4j>xM-e5Jswulu8CE-_ce;!bk{|lk24u0hFKbOg+vU#8i-F9t^Gb5Q? z@^5y5fg1a7>#um>M2SxI49+ZwD}FqipBx{;Jz6!hi!&>pB$>Q8&W;LaRx-K}jI^9G z$A{y|KCa$$DUG=X*EX(rh3ij06GjNbo>FLa=hk&QNw68Dul2N}!XtnEgB0HExMK|q%&W0e@ib|eS&sbJvmpnBR z=S*Z9Y4|O8Hv)VFUyPa^ml|UQTHK%6PiQ7k}mL9paVS4FlkItZDCfs=+ zbq3~XJlMQy;2~2DG^hyP5rwTkb$_vM=8)xFtv?XbmJC7Ps{E>z?KXXTo!eJPO>fT{Em%)Jm5e9HjWsYC5 zF37yl}@x2zHXwVFHi~(uTEZ}#ZWHg zeqYYBI!>}mxI~F&@&e5_$`lI|bKkm%hx0eelV7Z*=nx*c)k^b(-s4Mcuw?@PABs$r zt_1L9rhgYTkoBpGDFHT3*ESN+Zs!_+*)>~;pDYUr8&ue3sef!L^4RsrbmWK!ZXcZq z@4t_5D=hV`ZTkan?yu=+2;Nu#8`Qes&2=ICh|S}0;Gx6eXY zdMa}IcK5mI$g>_OJ~0zMc^{$Jd;!ljFWM_y??YhqkDgS~_Hbf|x#f^XF^)j2q0zx! z3U#EpDZ(~M*T~`~_B8Ej*}Ki?O=i+_YiU_bq^PmSAhxW>IL3ItR_0lY8Vt@0QaA>9 zYqjlWR)mLaz{enJ41(`Y!grO*?vXJacCSeLNgZ=}y;9`WoDIpUcw4A_XUjHQqro(> z%=MLb&;1|{zth6(B2kKQa4Ms_LW{e+v@gikaF9LC2F7A@7vp6)&gfX&N`Zd7fxHm4 zLHJNzBJB3HZh3qO#!-B{){UsV{cVJvPIrQa>DtYNo?B)g+3oV8aw-fCPDKu0FPV-! z?t#sHGvPuf_f+SFPQ>GnjbxzRJm;D`VpmoF-#6dQxs-EN*17UXV+1Mw`Y15gbzk(*fo$Z z2?xb;@D{B61Bh6o7ls#My)vQI=}|}y8g#}R+jPLuUxI(<<4~pa=0q`01NejCG>iNY zR8LYKfTR+V*s^uoj%F4tLQx{_vXV;G@7kgDvG8f%L8rJ{CR?FAN_L6%My{n80mAI*=MNrbRXZ*==9`c zCJM(Ltd8#E+tr2yjaAw)5iOq(Nj30V5w`9n&5!}DS8S6=$1{3KBp(Qi-WaDyYh;Ut z&W`G6ppIVN{jQuTr@KQs(pk6-QF(=^^Q_V>sv&*!nwS-f& z_2CKUPZ7=hLf(W^ZQn&W-IvJuS`tof<*;2HK{!`#nBA~%PAkU;Bb*;YEIKEg!W@h- zRE)~=o{wxi`~wgD4BdK@@`L61cvh7VPxg{!f>F((1SOB7+-G*eFoy6+%88aCQ3tSq z$nfM)EHz5;)XW6UuR_CxG-}X=!5~edgqTNg`!IOUJa(^*#}b&GB=^(rG2eR0jE;<8 z@Zj5h0Xa-E{e#?j627GgGYPR$89G@6sYRgnBsD0FD2QF(a0+Rt5X|0WobCp7?lDfb zb)D)V8r_4$F}s?K?&I5fjII+Mr=K}>MxnXsVPtw4hCe)BHl-M#KvR*J5MKdEz4bnk zuSLEj9$znej>reubq4|B9-7%jvZO4?Wwp%?S&gd!;%BMn)^ipK&RQp0zgd^ z=qCmJnAwKRSJo!|Jm1Fi`lKr?_4;{IxNXUEc5ZI)Oc-vKwr0{z z`KFu7eweII^@^$EL*#R^b2*WH$)TWWWvq~ZI-Vq%^Uj=6<1z@z zCoI?Nt{o)30G=r4DqOL6`b2GPseE#zOx(O>|8p;I+q$)JSIdqa2q?8>7Tz=77L;Tp z@aQ`zICvL8ayyH>rsSAZAzRn|IeIRsrsom1@7U3}eb-ic0s{$YdACVuLpm{MMoStW zF#eLyB!wR-P3>gZ0shAX_QnEB&o z!(xD$K$)%8-qs1XlE6Z8WS%!UfZwfAR$iRRDJ?th})|4chy%Mno!MGMN4%Djq`N*slzci$uW zI*VcuFxD?%79%T;VmApG$imfdkaS->XsohCIQcGcIr;j>RJ6~8JMN>TA)I_4Z95ov z^I%QK=HQJ*aPnOrytzJvA2E{7tW6T(|LjkM%REH57(}>eq6B1E5cG+%dq##OX`J*U zc=wJB%k0D;!{s@WVZS`adNN$$ONJ|a$#8`)8Lr5Y3|CyPU}P9al?;zo!3T1<{aQ>|^z0mf<;jYi95Q1rVd zr=$UpxsQ<+;=h0Ii@O*ZcMg;KTvonGzoYyZ>?iW}*vY9V563?XsO_MvJC;ntB^>^Q z_T!Pl6j|nnFX3CVi#8i)qbVdIW_BUmSkDzy%qs-n2$DFv&Un3}QO42ndW%*IixAZz z+yvBWdAKlADLI>A4@|cp+K3d!^0!*6yGndaXD}1+5O@?vXZUkji8|2Qz$iw>dL~|Z zlTj~bpVecb`m=pwJVi9a;JHcobUQo5%wuFRgF@9aQbw0BE>lMs|ARvAu`@c|u2rlM zEvzC&(|B?;0qr^lR?Q}W1|37=9AN_~`;%s35LvF}SHls-)z5loCtV$^cl6HD9-pH2 zr`Kwv@RdFb#``&04sMqedY@hB`R=pj_MO>U&*dKSPKDzsJp}2zmL$F_MdPa99iQ+#*uBDuH8f` zUzQbn-OkySTZk!x?l)3LHp%Kz!IUj>F=Yp)B9#3v;?4fIcP89=ADOcBGCbes+xE8y z0yhFR9gV>oHDJm%1aEE#;m3TMmI)baEAwN2s?)TLpO6^D!IL;Ensh1^Wq3#;D};QT z9b=f2V7Z!YaTM8?L#gCoGLtPHjG7mb_+BF+vijNWEZrajinK2jEkB0tFqEd!43T8g zr&a#fbkMYfTJDi8bBIdkhf%`*^oy8B<}cCC7l6F>r#Dc3e3b+rZEwnj~Oh@uNsC5nH_`Pu>Z1a~1Iqf9PN>5f2UJB3a#oU3+k)&Bdrf-=1 z{;3G9WfD=>GI=0UHGg;qvX3WcseW;+d#50K$au17O7**DoR3aE9ZW>w55|}>RUIZ& zX7D@0;&KQrF^zt)d#Q5B$p_8>P|~jVr$WCX<5C)HuDio>?1L(!%_ z7(t(V`EE+X-LbvV?c4V3iuUd3i^ZZl`?f~6@7WoRw`@-W!Yd z?%djkC2O{C?c2M(chBDKd-rVH9hbZVdjuB5Yd-;=(XhYsH?ZKkb&V5QCbT&Hw|Oco zTB5d(E9ZO#mf8-Mo2wfo8JU&(lhf?GSI_Cl>_XmB54H3Glqheg4suuX6j1&TBD2e- zfa2-NZbdjTxNy=qUE9o6Bv>*Gb}MIsL#JOz$5ez8(?%#Ut+i?xr?hj$IDKqhaUaH2 zd!Ewb(^0npy(#K}a@CGT@jXkR;L}r*H$g5W1!J^?5j;H!6NDFw!a`p;m`tb1lh{RV zK^N_a(T7;5kz@WTrZ4gt&2M8~jJuTZJe?+^I=+Nt5ho-n!7%?d>TZgQ} zkz@xlM%tQfIh}oBTM4LdwTy)z3e2X-ud%EGmdO^&5eq*se$gjI0Z%%qxc(7jp5azs zR3UN|*Q&S9W%c9f06IXm;+2t%$I3V*Z{ zL*I#Emn^gQoQ`DFWYFE;Pl}_E1jg?3V z0Pil&G5hMK{NeI`C%|EO!#<2UpK;9d8FTUV$jygmexNeuM%Sx6v%_&?G;OI|?0h$j zVa_$_&BN@YWyh4a8Xc(wmYZkZGDJP#n$@&}RvW&%bC#r11n2e7H^1CMHv;In294BV zBI_EDqvuOsB7f$K$XU$Z-Z0XwvAFxFX-45llXf)TY!gJAV5nUudO=rc1G!)UY#SzpDWa11-D$- z)B$ntAPsj3eSg5IgNTk{@Frb+v;Ho=C5nr0aDwPV(L@ODy@JY2l-x7-UYX^5(l2-U zy|Z4(h#q*9l;-H(>lgc@*Qu2Gy7!j(y7!j(y7!jl=-yj)xs18@;;6d!MqgE}7oEuq z$qY31V@5i80dWz=AceqF!Yfn$8BbnFzzoc(N7PWl9C&^iPdvrEj^4qQ6VwWGI1MsT z+-AyoObnflW=3H#k@4aL>|{j+?yAx561%BV7W&@Z-PUueySs-1-zhtd=j8T1JG>{6 zMpHR?w4=MF=WI*QPFagjJI;d6nw{5p16>`R=$_p*`#0U|YQ(d5X{B8Qs?W>>yb>HqF8lborXuWt%8S2lkGNV&Mi_<#GevH5J)) z6>gvhJ@$^4neaA;3FOt!%!Jo}Y^(K&*qnWB2Lf*%sOi`gys;2&ppOJ^J`%!@*nEI2 z-a9m5G79J+36R|g3z)>hv&ak}7G|aS!089YR!G9FfSa3!kM^dLF=kPxXaH|Win88;MUdw6`jdHx~ivSS)43x;05dx+&U}ek}G;i*t9qBjTFPI!JoGjO` zz+IEA7LXvrsn1q+J*74$?XrmYo^ckq`k{yEx|9W_nwlN=h3Ah$M9Rx;+s%eY#Vs5HCub zjy+5F4_{I;F#EG--6(j9sl|>a#^z+tsLCGx>WE9ri#@Z}?_xr$uL_*>yX=YZOdAM? z|1;sKy%Mdf2kQw{ec887gruRMP=S}aRNxOd`zB;DJid~h{VLA-uy2J(e<+w3c8}N% z6sf=X-vg=^U0j|hv_NSxh?*!u+_eo5y>o5x0_!d?OgY~*5mfF9GQ%^a#9-S%mGzf> zWNcQEPyLc9w9Cf}CyI0|B3LFYgg&s?E@}ORD@C|cYyGy5xPn|>dSkVV%_^QOx?D6? z9A`&`%_Ffz>OU_d$rt>{3FAr;zRHh}BaICDvk~%!AlvYuL=B z3VURQdEvtwA)aDoJym&xc2CgmD0XRbvtX#eG2svKQ%PZ`Y54%*!Zj2Fw^drIq_9JJ zl&^mFE1$g+X_<<&+==+7sC#TC+;$%|Qo;91Sdj1OaOfMe3*a` zuIQNnr1Z>*2`HHiT@EqtGaMBrpmh8-InO)#6S0eoLfc|a+o>aD17o3i$^^|JCQsbO zd}uD=dsnGI7-x3>Fa>oaIm9MS`$eM_woZozpse z#^ztpPRAe=;{r!A&LR9){8oHh)rQXzI{Z4WgEd&dS%ZyN2WD#9UODW-2Y(;d`JMIrofFbBl_GvIjK0~}XyiMGj4x8(4MFO+E{hY1Cg zo(aSY8Ao5pkIG~Yj_;K7iW6<0>B}4$Z6CPtIxmqGb1L0>qMp8!JNidtPg((94HGYq$r9 zC1=^0Q4?vF`#hqsVS@Fgm9ggCwp3Ei^?~&cw23FvEU6(BcXHHxD0y{uStl<|8bL9_ z7C}EtaCCrnHZUy~l{4F|^-A(0@jlkuzeYRbE2TL_*UT7!ms1D0WxBS7EGu_4;U1cb z9J&rS*pnU+plv4HF0qO-fqcAfu-t@;CzBgdaYo5!{3&^n5~flxQ3%062m=#E_bfm~ zQpibS#--j)_A@YW?*ddFvc<5XyHv>Q8e-GcrTddpcOLM(fag?kCinp6gm+8%Xy*ub zHN5J3j&^^8S)?d7HLZNb3wGAp9Crn~2UgiR4|aI(58KLr(S0h|aVg3V>#)KC9Ej67 zC_^yWA1agYdIyU~LLCcjuvjoLaK3Eb3X(S!(CcR7JQt_8lnIVB%vKxB|7Ua#X;kBM z^$?f?y^@bM&w@ugX$cf{7Vk+{)Ehv4vJse-xO!&}!=lDopV{MY-%W+Na z`9yEl$cdxQArKbe2P@IrFM~ywV(#(bxE0yti-obVSSn%bl;ph+u^WsW1E%EWxjG~~ zu@&qP)X-|27LqKb!AlOuDe(l1@0kRpqUFJ02G2bKlRIu0g+;#493C{bZzaq8_FX$Q zxsKS|5Vs+8C7sBy6$r7S4_^za&rHCOHxwHq!yRCg+u+!`d}P|wU#1|Ke&obe($3P8 zB{OuvOvHupA#}?2J`#YI4cck%nI-?$5YY9ETlQ!HQ`-;Px`&RjY;9tx@zln7yTIo(ZcJ16x`r;mVZ0w%7BT=O_<(R5F8&w= z+?(mxFmmqkd`W}Jcq%z${i1G(Bn`;8IW(L>Z(<1$2rK=yL~nv2ZU*L~qbgBgW~C*p zvPEp^u5#PaGaEwFSk0@1`*+2&Rd`0M=rx>4#7OxL%W(qZDp4_PKu&VxX+ef97*@YQb{c@ly{sR{V#<5e}?;j z{flbU(4-YxV3?zSNX3LjBoKbNW(y()R#v@o{JjN%6+32^Z+I_QDBNC)U2d)k|fuNV>xX+SZZ&YTjI3rd{U^LF`3knW+{M#221k_3haJ2sqgaDMplg#qmRi)wTBiGl@)E@CT zt9)qNd?64;Y%U=%>;A z_f<#Q88(G|dR513Qul~l4(l^ELRJjxWyN?Yt{7@9{BN)#Ww=tWyW)~B%O}H^!(-)f zc2pRSiqSv9Ym|_4WN?I(Wh6N%lb-Z}!!FlcOkajNHsHugd~u88l`33PLn;_HbAgZw zlIZua%ARs4iPsa!r4-z3HGJL^4cU-$K%G@FRi>jRA_vYgTvJRXTa7>Y(*N=&pZngQ zfAOdOGyyD3Ou4tw7y*4im3>J>_+vqL`H0TGaEi(Y$8YE`N=%!o|JceJch`i4T2 zBz2H`rAR|zwnF(BvgP(WYY6g%yO}7@g!&>Pr-nm~%~en;P4!_97G)#+i#_G$53=Q5 z@;k{ccNaP(l_}Xe_cibs#00ftSv~JXtpdbk(##@nuk+$V8Y;O+!v@7xfh;Gsq>gq{ z!pSbP$CG^!wr(g}i%&q&6-hlz1=V0{NJ!agy<&FcDw2A77j|+g?-Q*g-iEX?5R%r{ zGBrulbnO-xgEwv?9m(p=2mx-Wx*dMxz0$z?#|mb#y1~j_IJX|>>Tzz>UMjX`H}oi2 zym%EUQOW}=c3)pPQ+M)}!(Tjxt7^!ge-f*MGvUXi1oiQ|45pW11V7)ty1hPdqrRrI zDtKdOTXkny@cU&U{FoQCoUFqqUeNlI1V!#Uqw*FaBU6qJGxtWoG8fZKb)u%K&FB#+ zo%Y~8n0sm0O1pj7ooGOe@iFLc1kgDXMXjY`49{wG^)=JwcG?j;J$J4bb1C|mc1uqi zsN*ZNDj3n}$G!4X^R?7W?NN^!#^1;8KBEJdpYWt|lk(GiQUN(8;t#D2??Fo{&@dMO z&`gon$DQki(lu4)@zIu=)%aSp@wap7EYHzYaYo+f8B27(7u@_2J_5b9;jb_tPDO(w z_*V74FSL!%lOa{r0A+%hgz(9SJjyp8Eq<;>X{m^qBzr)Ps)o3{D=(w8cgbt1q|n(A z7@aNg>6OkX9fE%r#eumtC;*CaMU#XLS4wbYh3f|V#FbK9(I#ATDGkadOD>m;mBran zQ5uww|5#2V?sDRgIYDUCF*C_zzZ@O%KOD7{ogo%kh|5YJT8&PtLoZ?xw;|+H8f4<2 z^FAgUJ8n}2C`QQ}3QSTonM@Yi=#YiD!-{2VQHQ`sCR&hP&BspCcR6T6ddb$!Q6Rf^ zj*D>8$~cX`oL5-Rdud4BDrfY(%8cV^$DA+7gV{)29gq#@9;D!oN%X zgqr^a;|(FEmS@)p+_<484^`iqi#4VcevE(B2QLzu=7UPN@aZ7L| z7sM@{B)c%V0Xgl$W#eCzVAb`KR!0k67^%hV+zhj5E{`>IYVKV%aIYo^%o1vQVsdOKm7 zt&s6{;vW%~{SL>ns&Z8!vtq;RnVA(kUOE1D-LCxAEB84fQ>a&h?Ztr`#WnCtxv>n; z)fBwh6v7WZbj@dL(I%49*uCJE|6pZn`DqD4oe8+(xokJK9l_TE1WfvHte&L|<%$*O z(u8r=r?|y~>HVlHvx|A(1;Tjk)K$D5i%H50KJ>a2ieObd+MM;jO32_$y|U?A<4o;g zj~d0_N$q|wF3Zf&(m)K9lWLT9e>1e|xLi09RLsz-!*UUf&7ip8S1?Yr!Q3ocnkZ+6 zXkny=L$fFYm*l{JPEM4*W4tcf>msuihh{Q3FR)8ne+|@Ff7wTu?3m+S8iTXU#i;W# zgY1}@B!hFV^*be6-Cd+3cWvNu!oFP2Jv3l@Bu+9@lf;RmDse{7KrJBAr#%S=Xl5LC z3Z5P-^@~X}Gm12EgV9(&9D|LGA_X=XG2u0w$TZ@>l42uvB!jV1auP8(ly+|j&eqIc+e`1uGxiPgap@^tMqkc)Qthe~PVg_shJFZ6mK$Wx zU<6r+5*bwS9un{rPng{DOC_4Y52w?YhD`(_nHHI_xm{Kt(*p47eC@l5u~rzRpYBI; zQC3`7zSZV~Cw*_VMYjlQ`dxV6)}wl3bKCdcFQY6TV5*UBxd)S&LkaN0Sda2{ob z;UKQOQIsuA#SwlyYS1jGlnmGb}O}5Ubv`z%TT7#}mb3aQ zwKL0iy>j&JF1up!Uf6NlLlHS)d?G#0l<0yiQxovVU3HnnZ)To(NPvJigggQlJb$#80>rH-WZ zLI5spwx+otBRL1l<;|S1`3%LuO{SH+g7-pOXW+Rw<4TC?;Zk?a3%l0=~?40(A6t0{sJDmRBG2t!5-Ih43_~*8w*t zIXG}T(g{xtG7dV8_<+XcPT}S%QIkePGqBpO)%q*0>hyEIYogK~&526pK4@4q>Kyf$ zC7{ZuSC3eC+DB;hs|E;sTpQEsR}E}*oyJdGDZ@RRv{%Y;rBQdq#g`RKR$ZzL~Aq!Hn zTb@i?In1*~)W>Xy#f4{sh_N%;MBFY_RB}%)78{EyME(q zL$98Gt>EXLx(3!@(`@_c+wITa-n{Qx+wX2Za68`btOvYAQ|;}=4ex{lOPcO1-afT> z`^=7$v#p12x1N4&;%eJ3eD?Nd&d;tPzp*?q*Ia@u2?jXcK)JjX68hq56k>PZ$OeCqK3ItYLmS2bq;H? zP!UE`sUCh`4^^rKZt@dDlnbe2+fu1Rtd%n;EaWLAj;~fz=*VJjE1J z^C?)0CY)xu)M$!<1C)1*zyRyAsWFI0E8niqAE_7kR78Yi?T+ zcF$ls+X@ba$tjjh4(Dy2rFm~#J-yA>(VYKxxC?BJW%VSFa_+(Ljynqff%PKiexgFy zW<*L7?P7leM@UgHI1L=diYrC|Gj0e`9I<(}aic_WiwoT|(}onVCrfiTB78v8hRh2C z*N##q4BySP@yukIPp?Sp;o4xNDDyQ^l<5S02*V|~N9&3Kx45za!_@?SdR7iCn=HFr z#*7p=D#CF2_#FucPYp3CSd~O&_&dNciC^f+MUUt5Iva^^ij-uIKq(xI_~uSAdRtG_v*v5ECkP@ly>TXnKa3>ZClkj z)xoR$@6`#FED^U=lO-(Y1&s~mT%u$HU@L{C7MMwi<{<)3+x3mqSGGLJAu~#&=1kq~ z?pQN{=G(Xzpc$@UvLI)a-ganxw_jUy{pif{Q_uj{?Y+KFAD8pMrt%j0+=cCn12-1e zbOwSqHo$RYU-0I>5Ps-Ajei?s=cCUpf^M^@2iN%q?d$!{?Jf1h%&RR|yR!sm-1Si` zXHW<~G>s+|uo%P@y@xS*!s$JX$rDbaP4xg~G4pDpH2|GnZ6)K+N#Nn}I>aV9L?>GN zRB&WMyGCiBYo9Hhvq?EgxiPgSVtU>tR@!6GY zaX8_M;(K7%{(6^)|L5CwwCxVOxx1!gZSY1p&|+2a=Bf~W%)6O!)U)=Vc$w_aB`T0+ zpJ9TT$Y8M(=ugBdo-9FS9~LurCKeU^Ru3dIb*;d}ONrPh3jpUivn?+Qi#;QhA;pZf zBp@|u>tL zy@Pt07dDya(LGOO-~jd6&a2{S;z`0Dr$bxg)k`zA2R*8u4{d+`sM0fWc~6>$F|nk) zH_wDvFk>AV+>mR%j>*yGWqHt;kS;mF1ruU{juI+_rG&|x2fr|+r${H_-YjgoX>5)T z4dJ%Arg3$aP2-7pzPu$KN}!M=P#tJUT=q5Eh;dzgtq&5TythOm)UTDCFldIq`=_|#BVtr4+8lE4fLjOLH4uI`0lfhnQ7hoUN_AkH zsJv$j3rTl^NpccU`^=lty06BasTOm*Yoh83o}M-cA5~0SBb`MDWN-~HL3=jut9^Q< zoA<$qY9HaF2v_vNM+jH+!bdT#yk-ml*G2HO-RZa&E@%>~QY@lF}-f+PmNoE0gmUn$ zTH#0uHJ8yQduAmEipn#rVT_u25keozvrNHA1B}Mwzu+5;w`M)nXl9tgJ!3GY zjiC%_(c|bX!MR_5yf4N1{@kxyaFyr|>loTk8{N-zcRY3abk~V9x%lStP%Qd3R7V!& z<-@fZuLvjT`I?OmBuGXEd$7Sgmoxtwd7^%FqlLU}kmfknA2p*fo;Df23(0ifnDyLd z;=*VuYNE&RAfc1;Z4lF1|NOJjrt!9>b6cDC_B1{Ba!cc`9h2+o?P0JvTi$im;L%W# ztxPA-*9?|HF;O>C4~w)z$vBT3BYcpBAkHHfKRHjbd&s9YTM4(yVY!@2wpu3F=gSl* zC%98~wkGi+rfg4ov{%Norp=vb#+4G44Q%3U41#j1Fn>Cs!*)sA3A$t)1=KK1VS^QhS zcXs3c_ab58dAi({Z~1{u%qsMf1?@$F8$~r8TZ1>ZzBH5?jzYl@ja?iap*(A}(g_p;wz&o~L$C#^W!P6MAmHq7(5}N&$E_-~!j^2o zB-QISz=($s=+@Jl8t(OhxJuYpL}`v^@K5V?Xb{E#3)#hSO_g~;nPpX;By`g0HjD8= zaZuuL^jU%<#YCd%z}LMhhAr1F&eT5PQ87HQ29P;S%2^D6j}SsW+#!dZBczBL2p7F) zvHa2!kyrKmFK32Kx9tWl(2d-V3jvV&5 zob8tZUsW^C!EjiNyS)2jWjst;hiH7617O%v zlpJ7uxr~L~SWJ`Sip0_h!wAJQiA=Xh=(hCvOoFNVevZW0qAXeu!tv?0h! zc%I?!!jEJ{F!JZhkr8m|EpxnUqU;KupEl?%%W`BN%6)pJO9h0`Js<5P!u5RE2ZZhE zwUbELR-P04P%>G5xt!@Oaa7oc((&Jr2*6W-QGV?x78Hy^c?SI8xy|MhUG6WEG=#XO zf>c0Uw;}ZyE>(?44K^pjEXdaIQE*^PHljIct7@1m!mKKcpQ&^-lot>+RB%NN)6uYM z*<;Bk$}T51rHiHr*89Pci$wp7fX!YH$I;!}1Z}^MyP%<2w9uuY zS^pTz?7V^0GxaU+RTK+-OjTel%r`UP)hQjq!|cLh}jg@0VSgcmIoL{iV$dg2Fd@{R`wX&dXjGDDIZ`g z;q^cSOAOI^2Hf62#st|Wv%;j9vRyO^r8Zk4!AxGj(z>_@?YZm^ydAy>KrA&p3d@r) z30sS|SoorIdUCe++onV82SwyR8U>0Ryi!$P)BPsgyU=5_DIo;pC;+jcM%pIfDab}hJ z2V*naUn^_P98O{BkbW#I0-cDQk(ua4C~XsceazT-atH=Lnqt;0<+ekb`LIgSEM!;p zUA3n&bu~E@OO0Y}>E^BzZSBWsq+ zPWW1#I7H)aZI%xmA1Pj&susuc+ZE#Bnf0(t{6IDv>pbbO8j7-E6$`P1E7`HL70O4* z?33<=&=>`=wCb#|kHEXYT8Wjjqg}-KS?0s=2?d(7E7){Sc+1&rs?DL+U&fIu6P7{EH|(oTBHEFPoaVv%%DX;1nA*?Np-)+gnmh=~^K zDxovv=!0Lwpv`;<@FcRUQJbu0&Yi$-2IvX@Ah1NSOiG&<%`plN%3>Q_$(rg4;N@?? zf@NlIJ<(7_+6Q_w9NQJcDrI!nUeICwB5&onLO#|kUx%;X{5gC}HmED1X#^hp8{^ph z^C+l9@_Jh~aEIm8y{Npb@$Fi%o)nT6KRZ+RRTz5*sIZR4t{NLChR$z z`dVrxyxCnAXYYhJPlY%C{W~S7N~92L+uhb0c(b*pvp9I8vTaLeLGb$pA^dQlwA8H5 z=PK6H6s=<7!OB$}{RI_Aj|>hb;*^&V5&;heL0k!tONu?IEj%x<3Nuq0PV)z^WsOX7Fww{y4p}j$_^s9^#79X~9L|Yg-J_Y&`{vKW%}R9+vl4qL7O(5WXJgUw z)5FBObBy(xmMR^!8jhF1uHHc42BT7z@s!2 zbU~yEW1bQjzxoKhb~kO`YQ&>sA3HZAADUz;VLyPZIShGrtjBm7X+eiCAtrgK$LK`w zT5ayq|AEOoqz(<453ErTBTE2`4ClSjW8>lJxouXHI-=USL~op-Bj^bYSu@g8vgN!v z0}`no)OA~0V^ab-<3 z|IR#1)Zw=PG*F=~<&KU!ko=_dU@YkneL2@Dtcn6ZsPN$Zv!+DP5k}k}MVlsBkhtzr#sr@gs={s-w$0oVz(<)jHz@n^@%x@P6!FMc zih<2mi7`TaF#^ofFyJ$XmmboIj<0oS6Zspm_)Br04{BFum-CN{vyNgoEVgo$|1}*; zxkTG?UPy1H9b}B89sK*t7y|QGXty44V;-TMohwY2cJNnGcpPlA&^Ty&_K%53%%Co? zmbFzp@8Gp(XKIfSYq^&^NbzsY7BbQMTH+5+MGoI8nU0+Dc+a=bggfr1dh=^|uozk2 ztxb}T`Ea|;r#sy4-$>Nr@iqbjxCfi+GS580wASp8U86wqJ8iB2UnS{4h(b4en|}hg9AWKeD$fvA?>`{BHzPBGhjI zmw>lS*S0`ATHnN7+C^?dk(($|_tnpS<+FDpEmM(}JCO%B9+-vt1ub;KQ3BL_$}weB z*q=-|{sgBSi=J0CrFPaa6^x+LBL-1tU6xj8;$9gSnW9WEiI<$tG{n7HMq~jNjkbnx z*z%4AGhk&k;C{=($5mK{El>FuMiVB4b?%Rog60-J&=!)4zN$5mmn|G`qA{K?&2Bf- z4_o$y{w*)IY~Qj)85>DAg} zYIEVNBBqm7>ru^NF8@^}64D|Yz8vsUJ7DuH7Y8im1w-_|zywt2MUAHF{K$n+nA(-= zD1}F1`fEfeR!D|c(~IvCow$YGf}LH?Q{ZxEQ%NWE!Qc4_C;o7u%1dVpXwt%rL5>iKDSEpS^S=#-W zwJpcHG+89>zSuwso=;c5Zn1%Tnkxc!xRL?G9tZ0$PwwmzmPMi@&W?(sXle9Uz${2? z>EOjzuD8&V3H>b4slJi-kpj4Q zYpVY`x`*&7P$Loc0hM#K4|)wFp=QCeYvaR~__%e>@@0MughJPrqC??+8On%|Vud~! zCrPsC7DCo=9lDso5qy6OBLADw(rC2o-My7B z6p0W$s*|%Dmg<15e$-kO?pWKtYACO8_iyOgZMPR^H{K$0{T~5?AlK_Enf7VZbZsNVI*UvT z@$T)q?WBSV7K&gH_aZ_Mu2)Pmo?pMR#dmSVNxzY(f&5|wrDkCol4@JD0xRH3I<1^j zQ$&cFU=z8W#^pg_Yf9c(9N^ zjHLOFE94KO_mm-j7_Fy_E1OdZTf>6ruyYNI(&&D?JP9qfEN2m^d}TWBkIOat(7el< z@0+Z`RP180+%urrB$@e>0_jgoM9kV`9OQ+Bs7Mu7umn9ruyVU4S2Asty=R3KlzhLr z(Q3x;2qOsGN+?Lg*l(Eo@MX}ViM6(%(@jFX}AxKYOTJ}uA+qI3?>TaJpH&gqp$4BrUB;kI>UgCYu1>Kux zo40&B^+xLT=dT^OwdSqOKiqt4J{>{ zxH2aistc>p`s652n=09Wug5UCH*GM32Kj6ZV{(hcFT1`0jkNOtZMoj;cTytJ;T*$D zl3R4W(%W)Ne6Wu)*=ezlNhf|@f+acHa*_3JjBL5i?003+U3gs*)i~3_*)?H&!~{n` z0wIip&yu%%!hlfbSKgpask}ix7opeOKxzJ444wJs_zGS69l=U*%^A0eDhO%*JGza- zUbV$1b~AOG3VhiW{AGBr=(xxlO`Cb4qm>HKMn}d^uE*24EtPo$`S zG<^vHSJOYljf9eA3?-YdJ$w7<=uB-d88mlaKQ~i%N)xtr5A;7D5n{f8rm@nSBpw8jfHYe0oW|#8O^a7fyz}8fl7mk@X@cz;sF7Ag;gwnK9 zM+oKQ;}nE)CFXi?QHk+!Dz8QS6#akqyO3Dje4MRio-DZlPdUXmuP`H}SxfFUAG0;o znKEnIPe_jM3I>_B&cJgUDRb9EsZNf~(DE*9gD$*`RJ#+wp9~=xBKv!&AYO=tc7=3p z)mRYt;-;d&(25*t4C?OANd6H1hNbX0EVA;8O_cOVNf%t4Mv~RZumhUJgcG*MA!QKL zaB>56;=z?eT#ZV}`7TWcG3n8#OJ~SXxx%McYn1MYKf!TU4Agtiv$&Lsfpyv|rMQRq z1=ogq%5Vi=gnRR7*9#{rE?0~d#@SKPu9ruDA0LE-s&-li{fWt*=GOIV zU)tWeZ}a){O^-dd33skfW%jX3)`?mjH}f~jUKhEv_-DAnS}n+})oPrCiH2uzvn|4{ za9A2lQm8maupVy++TePo2(RbVrJmV9bQ)=^T8Gx9AX_E`hGhH%bTE4Xrr8i1U8GYg z=J#Za=tY^kFq6g`9DbF(G$(p^H+rC65fqM!Yh{myCD~PM9^u1B&rh12%s>7N%3GS3 zC(r})DD95X?l|pEV3#dHsUw-hV77kl8gzn6-5edwi_kZS6iVcd!v@Rz9s27n+R^yf z+MO&*kWNq5OKCn&QwiHYljL@q#MZ_oni&)tUndRPb98zu@eK!19Fk3agh@6#t}mOZ zJ^IRFsD@Uodga*L)yrO8`;GWa_1d?Wt@=j#we4Sj>FcZiI#9TZJ-NNHZn4 zipk;(QeW|Hq8R)F>Y)u9E9vnCS}FMgewFrG>$~J<>~f06igZIcrcREl$(eG#%jP?v z;V;QC;c}@@uQYrOqE}0G+zjY?F|PROrAqaBsdy>w$z{EUvdPlRrDJ7rc69Ipr&L~` z4OGk~kMp#Dp7!TV`&II5{uVI6{J*iol0HFDO_#|-5LQ8lM|)`T^?K0i|B;%Gugw$QSrtC>W`F`moy(* zNmHdZ4TYw}Wf!3la@$=A4GiY|yYvtm#bEBKEI$$=e1TpTPh#f3tCMOpciBm4aaWK@71F}3lV=#@7y0x`=Qo7NZ=JRkQUwdri6T?cTl!-!^RthKNZ=G@Ei_Ofma@U&S0;w^~D5jO* zPZmy8uvXztPi7V@)lzgt7^5c2@0p>c+!~e1N&t>#+TTM%OQqEoV6c+G;N1-^RX)91 zgO}pkphBtgHMCUu8d|D+4J}nU8d|C@S205ijtUHxM{i?VyO0nFg$9;63D|P#!COezl($qX{60zrM-dUpAm*}Ap#2NXV)CBpo$z-4|oG8H*;Yr}Npw1>!d z&V;+}Ba!DCo{k+Iy8}0O*L1B7e!m>%hgHEJtP0`Bd^R*E*<#FoC=X^IOJVyk`$+%f z!|aFjYe_J(Lr6#UJsbNcTJKgf@s0kg7HLjEAgHn*%_==h@=chSZF2^jwLC4RzVjt!Tfb%G7|)=N67<$ zaACVbt~*10r&5V19D1;*S$a4|3nx%mabMC*XKa2@_T3k#SX(}!L*6i5yJni*oT*i7 zaB`Sz?W#GQL)pDr){s!l;T+nftkdQ19Lg%p3(MXRSmwLRy&KE^hOo@eYv9ynvi5&Z zfwM&%&YG`1F;jckqu_XOeMbKhXskD45$HP=99IMKfe`zx z>vYt5RA|&0uJ}l)ceLx$#``$+oH^cQdul+y|0uG87y8CJ2K{0kS>&YNuYw{cr2@hp z4-e~8%;F|Q9vl6#35uYdHVk>M4U8StYwFr~S zZSabHCVh1_VzVw?H034p!UU{e!t*J!f04K1{3gFJXRvBn1M8`QBeb(^;F!*Wn-Q|v z{~!pc)3P)C>HdNc;5Ts_DLBg+L&FzinyoVs&~kiMB*1cJzUrKcbY6dYI&$2@+#H+< zKXyNv8!O57kvJK`n+5sg{Qy&Ltzz! zXV zRCFd~(M=d6i6T5U)fh}=?LM#E#KI2F*lo=jL#vT9!YY3V@gHhwF`F@4qVT}XQ zoPo0JseM4r6)4=Lz?w5qSiPcCi@O4aS(|xbUxRQgbgflPPp9<{(KrFjO#O^J!-Yqxl9W zkq0X6%=mr@jhw-6TSb|nX*>lhw z?;t2xwpw@?BQj>`3N^j(J@6@cu3&b-;;&YGrQ*(lHB$@LymsPh%dhSK)%{nuTwi_r z$L8U#jm7rqErdhWq;o#RQK*R z-aS;e1pXre{lFzk*EMiaA0|-O<`T=JB0xcP(IcLzV zzXau{m&ab4^zyc=G@pR2Bt)uqcEd^YO9xIUzeC&3W1XFx05m(Et zMFQbRN0R3WB(f-LQ(!!31QINcO&QG+qG%KXYu+Jx=uC?&B0mKsR76ly5<-f8t?6Lt zBsdYY1W88fBAP2YB3I>XDL?8abW<+sW)n7An@}?OnMA7W5$j;6@L!|5vfioaw zh;}6jwBhQmnc7x;wCnacqh0SoX5^2K+?c-V8u6` zmB??~{dry>JIaZr`6LH)hsl5LU?%5ctjtC~C%a6}K8r~6ErJmdokTNw<8{nHv68AgAmnOEg2$ISOkTo;4$(nAJVa%70e@OVeOL^HjSc1Y{doa{wGh1Q zmey9~QB5x<=)ls^A~3^l{2vo;T*rq5PGB*|jrCWHuf=qJ%#Th*9=!%vpDqt}?4Akl zx!>5ahzLC~Le?e;y*IisUSOy9o^(ey7UUe=C>`~#2nHkP=*9v>GZx5bMl2ugh;9tp z+G49_B#z82x{**(>YDAlmFUI-5#0#a9wd4%1nGZvbI_-&%I=ZpM zH@dMDSJqjdoP9)eM;WdV$L`v2r5sl_x=!P#$N4chNzskLI6ErZ>5B2sO7!AP5ReOA z2kw|gC4`YBMSKBk?a@-xnP@Tv_ej;(A=*1U%47Cyj|XC&Hqc_wX$p`;6SkJwWPxOV zg3tbh`DfUxF?V*99giiWs4`tl2ys`vW1a|cDTYBGxmfU5?PCB@=~U^fiu|u=DZ5m6 zk4`}2;Ur2g@&jTKQAgBO*U!}M{e%gl ze~CxX+arDtpx|_CxFTlAq?)S}Y#noV2=a^feH|H@btfz7_uF>vbmXq~&sr^?m?n9>vZhSymY$~PUT$ebRg>$mASPwNh!5jA z;o4;MM==tlXiHOiZ{|pV=S{o>wHRf~@EtAIb7bFev??7X98a&x1Fz?W(IkQy`OBehS{M7#OX~ms-`x4dv{l7%{G8q1!U}`(XN46g zP-@{asEm=p#>W1zxdE|5Mwm?5O;%3hp_#x2HVZ}MV7^o7NkXnfeKKIxO8 znaOUh>;A;(i!pY+TVhO1{C)3fu@GkBn+<%<>F@VDf9}6?PR~7mmS~|0*)>jkcT&rE zdM;|u9NKtsx60<`^#3iJ5j`3cvRGXkp3#L-Ztj%#|43}<3}%Gp`Z3I1TZ*@AWN%LDztu~* zeIXm^nG`;t0obaBqDqJ1_P|HJ)Ay5ULDPA2M!rKeb%#PxHRau5S5v$1csj9(PY>+` zX*54if6pG6`~PmXj?r;x#o^pXQ^=!jqkjh^8V_qusnUw18`f0YBjqoIwUV41j`q6f zr1(sit}iT3C*v_)H%oQ>jbtQ_C!W4-*W-&bi+WPTO}Bm_z8Ia?(V=EfsWB_{>BVSr zfkwjH!|Gur&_N}zMzcWWC~)!2a$UD)Alp_6T^IQAFECh7psW|zbi!2VArKAt>Hsk6 zP_#i&OtblDb^FUp0&Nv}mmPucCEzUZDi8r;z$|bHNCH=ZcYy1_hrmr>8TbUa1$+*C z1>6SE=Ptemz6HJqFyLF<1?~fnfM0-Lf!~2F@D%t1_zQ4xLIqF*_<>fS6W9yv1C9fu zzy$CL5CLMqYrq0<6?hwX7kD4|0Qd;_7+3*51y+I2fG+_|krTH8Y_BT50kAukzy>q| ztI7*3sVg1=KLNi1j{!_J7MN}*Fq24Nl)S*$Sb7US$Y$N(%hI6=+ThJg>Ky z&~PeRfvP;vY)IUoJLNt0(0%^ekWtgN=BPHj^J@;zqka8GrN{6L817DbT6>*q4&O@g z>aJANUW++Y=VKS^Kf-O3V}^SVne>y1f92HbWGc{`H|g0=qhk$Ezfsmo7CmH9xBT+T zT&kffZ_#&%;>c{{HD~xkN@=^=M@Ee+wX0gHxyNEErBuoq14zhSM`Lpuo!5r0&)!Vj zSg@Ev%3^lt7&oeGjoST2rJoWx)9rA0n6rOa8D*|tON zU3O*}IhK+aWPB{bW8BcAmeQb}<<>wg*s~K1N!GyMT_~3lNomsvn`7Ju=Lp{gXCE|~ z5If3GaAR!3I6P>nEf7(k%Q=3Y8#D8k(hAElUI8a4laSe{gXDme)Wd(!Pt2U+bQ4_R zM*rdUupY>}*chLX;%ZoTK$`6;1?xep-VJ}CL~XXbP+DDulu1bbV{QdBSWa*mRw`u9 zWR4-X0&U$3Y#}D&N zKps{kW+`5L?_-1fBsWG*8|@)W?MA3sUZr+e?Ue}BCey%$$#&-=ILSx2F*#)^@}g8B zOuM{vxrW7%T(n;2?pi)m5%eam(KV z4pSUcJUdW|FZGpRunz2V6Q2aVMER8B0o58!CzbWo+LJ~3da-O4QJpXYISOPdpO>bo z0X-L$WxrkG*U;)^7inF}kX>aYLXitpy3?>#fo^%Y2 zWsjV&jahc4cQzS$Gd35EFD9oG)ARH*J#?izL{(udZZ>Sx(R7Gds30>K#%0!RvPmF< zJ-G-rM}CQPd!9b^XXn48^ymRNYm4DaE&Z`3EI%-_iWD!6Em~kjW-EWFOm8@JM(_?KK9L< zd9(gWmeYXJliv=|R|x?AWFVmUkU4fJ^9blb7ffIYiXbpvG({_>#5f-_<5ogRa6WD( ztubYc^9eI$Ns7ezq?xudN`~`e=C~y*vH(QzG0;;FfG+Ke036cCCuKrUe*ub_zZfhE z-sFcWF|-OsI%+tEY7#mpePWT%(H*1N7=nsvP$>uYsKh3rBwZmRMjZJvZTMn71YsP{ zQ1}QSpa?opL_Ma94+JHq3pBL2C#|5iZ(P-aR59};eX{g9{w&6;3+NZ-|0KguL;S4z}sv&j2=81o> z8G4UyLo~|0RA4JK9u*U$VdRWx6)$_zN8f75cIaK=NtoX$)YO}RVTnVi)}xrzG1~zz z(?D&w)-p^TVQ;c+I2(}q5AG?gW)l% zfmsRDSv#C%b&pvIdTA}xEhfDc_DU!MuSMeR3JYh+<8r%lG3h z+1p+ULZe|g5Z;>#b5{!HSgn(H=)G_s^s|=+K#+*=!<0Whow?R6-0jU^cLsMSaX8o!3tzLfF z%`ZPkq<1v=n4*0C+%9jjJygLe1B-$1;SxH16$)A>%AeYKeN=0}bI z(d$|hqmtTkHcDsC{%cW9ddy2(%O$@SO6<^&mc{gW%6^@l_G42&Z-;(pnGF5#x;gEK zEAzVYZbV<9(LV&Gt);*bgMlYrYgf)y$GjMMGOx3Y7Ffp;{47=Wx8gm#Kq31Ek|(qq y!~{X;gAcmV)(7QowDrO3-DrD0o%g#S()wVb8*PK+lt8!lZ1*>t`{x`1U)FzZc38Cl diff --git a/prefect_huaweicloud/__pycache__/dew_client.cpython-312.pyc b/prefect_huaweicloud/__pycache__/dew_client.cpython-312.pyc deleted file mode 100644 index 697a0fb74a3d24dc75f3d5a0da8f19b5e67db7e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2515 zcmd5;&1)M+6rWv5)|c0I9NSbXPSn^5Rbwk3g&tb>gW9Htf&wKUWg{}IcgN96yV7Q6 zWmQ3kQd~%AdJcvB0X9DP+Md!wZ@ok)pmd4xp{L$L9Vq0~H@ljZ?B>vmAp@HCdmr=W z&6{~o`@5o~5RB~ikI8Q_g#P4=7|}jBumC(n1~McI*^(+r9Ltt$N7RUqBUaRosWBf% ztr0t}#(f;K5_VEe`gp`j*=aTHU$FL@K6 zYs}P_DKSXRH8qQYEcvC)z9P5HdachaTPA3I#u?T)EYzfy+0Y`N3v_z0YcTgiKnGL6 zKSTtnl7Up&h#2ywq()j&KI$b`NHbVk)FENvhyxmj-@&5@U)z?c+>WrcD+voj+Ueu( zq_)&XIMlRd;Kbgj9RUt}1fv}VPFw_X(?VVu6=*Es)u=2^=5|k z4y{*+?!r3CJBydDktSYin3h4PH_00yMH#Wy=@?hY5WEZlrv^cKQH|ba-bl5{ zDdVnl!FY9Z`NPsRMkp&;)mCYRu&P^kO68_r3exOndC{R{9nQPBX4UoTqSJEA^;)Sf z#6yN91M(0Ypy0H;1jc5~bTPg=878+NWV}JL51_Svi~blt@zdnn{43MNC+4+0Xr-{t->|8H1ED$GUvBec8lA^Zswz|vb3*E-oN(4jTdp0R341K zOrW>tkIC=ZUiM-qd$F6n{J-PP_A(2d%)-{y-CNtYx|yY}^6_xIKaL+j`cOVvgaQ9` zkm;Ic6O6qS#&+FkSR9XHe5avVfrh>V3$_tG1BB-I#Bac#_=ko6DmKwec``N~*l=|* zKkm&9T`)7MdYzJj)^N*(|2*+?hb`eX7d9>zf+t_#Z+rOlPrc4KD5s--9Psmg=m)By z@5e8Xqkep2zkIxR4{xEvmqlUYl5oUX;mI$l>DQW5zvld0o#P1$^Y<#T6lD4nS^x$A lNMQ3Yy@*JXw1+<1LrZ(;Ju!c}hZg=BIVny5jbQS<{0pw!EeHSr diff --git a/prefect_huaweicloud/dew_block.py b/prefect_huaweicloud/dew_block.py index 799a053..d8ccc76 100644 --- a/prefect_huaweicloud/dew_block.py +++ b/prefect_huaweicloud/dew_block.py @@ -20,9 +20,9 @@ from huaweicloudsdkkps.v3.model import * class DewBlock(Block): - _logo_url = "https://res-static.hc-cdn.cn/cloudbu-site/public/header-icon/Storage/OBS.png" # noqa + _logo_url = "https://res-static.hc-cdn.cn/cloudbu-site/public/new-product-icon/SecurityCompliance/DEW.png)" # noqa _block_type_name = "HuaweiCloud DEW" - _documentation_url = ("https://support.huaweicloud.com/intl/zh-cn/sdk-python-devg-obs/obs_22_0100.html") # noqa + _documentation_url = ("https://support.huaweicloud.com/intl/zh-cn/sdkreference-dew/dew_02_0001.html") # noqa huawei_cloud_access_key_id: Optional[SecretStr] = Field( default = None, diff --git a/prefect_huaweicloud/test/__init__.py b/prefect_huaweicloud/test/__init__.py deleted file mode 100644 index 92f0816..0000000 --- a/prefect_huaweicloud/test/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from prefect_huaweicloud.obs_block import ObsBlock -from prefect_huaweicloud.dew_block import DewBlock -from prefect_huaweicloud.dew_client import DewClient -__all__ = ["ObsBlock","DewBlock","DewClient"] \ No newline at end of file diff --git a/prefect_hwc.egg-info/PKG-INFO b/prefect_hwc.egg-info/PKG-INFO deleted file mode 100644 index e948850..0000000 --- a/prefect_hwc.egg-info/PKG-INFO +++ /dev/null @@ -1,29 +0,0 @@ -Metadata-Version: 2.1 -Name: prefect-hwc -Version: 0.1.0 -Summary: Prefect collection of tasks and sub flows to integrate with HuaweiCloud -Home-page: https://gitee.com/HuaweiCloudDeveloper/huaweicloud-prefect-block-python -Author: HuaweiCloud -Author-email: -License: Apache License 2.0 -Keywords: prefect -Requires-Python: >=3.9 -Description-Content-Type: text/markdown - -# Prefect Huawei Cloud Block - -## Welcome! -The prefect-hwc collection enables you to use HUAWEI CLOUD service capabilities in Prefect more efficiently. -## Getting Started - -```bash -pip install -U "prefect" - -pip install prefect-hwc - -prefect block register --module prefect-hwc -``` - -## Contributing - -Thank you for wanting to contribute, you can contribute to [this code repository](https://gitee.com/HuaweiCloudDeveloper/huaweicloud-prefect-block-python) .If you have any questions, consult the community. diff --git a/prefect_hwc.egg-info/SOURCES.txt b/prefect_hwc.egg-info/SOURCES.txt deleted file mode 100644 index c919839..0000000 --- a/prefect_hwc.egg-info/SOURCES.txt +++ /dev/null @@ -1,13 +0,0 @@ -README.md -setup.py -prefect_huaweicloud/__init__.py -prefect_huaweicloud/dew_block.py -prefect_huaweicloud/dew_client.py -prefect_huaweicloud/obs_block.py -prefect_huaweicloud/test/__init__.py -prefect_huaweicloud/test/test_dew_block.py -prefect_hwc.egg-info/PKG-INFO -prefect_hwc.egg-info/SOURCES.txt -prefect_hwc.egg-info/dependency_links.txt -prefect_hwc.egg-info/requires.txt -prefect_hwc.egg-info/top_level.txt \ No newline at end of file diff --git a/prefect_hwc.egg-info/dependency_links.txt b/prefect_hwc.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/prefect_hwc.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/prefect_hwc.egg-info/requires.txt b/prefect_hwc.egg-info/requires.txt deleted file mode 100644 index ff1be1f..0000000 --- a/prefect_hwc.egg-info/requires.txt +++ /dev/null @@ -1,3 +0,0 @@ -pydantic==1.10.11 -esdk-obs-python -prefect>=2.10.11 diff --git a/prefect_hwc.egg-info/top_level.txt b/prefect_hwc.egg-info/top_level.txt deleted file mode 100644 index d32e0ca..0000000 --- a/prefect_hwc.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -prefect_huaweicloud -- Gitee From 2757ef1bc4c743c5d0ba1fcc29dbfbd8f8c54fbb Mon Sep 17 00:00:00 2001 From: Lky0312 <523175094@qq.com> Date: Mon, 26 Feb 2024 11:37:22 +0800 Subject: [PATCH 07/11] prefect dew --- prefect_huaweicloud/dew_block.py | 662 +++++++++++++++---------------- 1 file changed, 331 insertions(+), 331 deletions(-) diff --git a/prefect_huaweicloud/dew_block.py b/prefect_huaweicloud/dew_block.py index d8ccc76..7ae09a4 100644 --- a/prefect_huaweicloud/dew_block.py +++ b/prefect_huaweicloud/dew_block.py @@ -55,7 +55,7 @@ class DewBlock(Block): title="dew_parameters", ) def __init__(self, *args, **kwargs): - self.dew_client = DewClient(region_id = kwargs['region_id'], + self.__dew_client = DewClient(region_id = kwargs['region_id'], ak = kwargs['huawei_cloud_access_key_id'], sk = kwargs['huawei_cloud_secret_access_key'], project_id = kwargs['huawei_cloud_project_id'] if kwargs.get('huawei_cloud_project_id') else None) @@ -99,20 +99,20 @@ class DewBlock(Block): sequence = sequence, keystore_id = keystore_id ) - response = self.dew_client.kms_client.create_key(request) + response = self.__dew_client.kms_client.create_key(request) self.logger.debug("Created key") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def delete_key(self, key_id = None, pending_days = None, sequence = None, **kwargs): """ How many days do you plan to delete the key? The key can be deleted within 7-1096 days. Args: - key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_ Id: str :pending_days: How many days do you plan to delete the key, with values ranging from 7 to 1096. @@ -125,20 +125,20 @@ class DewBlock(Block): pending_days = pending_days, sequence = sequence ) - response = self.dew_client.kms_client.delete_key(request) + response = self.__dew_client.kms_client.delete_key(request) self.logger.debug("Successfully delete_key") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def disable_key(self, key_id = None, sequence = None, **kwargs): """ Disabled key, cannot be used after disabling the key. Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_ Id: str """ @@ -148,22 +148,22 @@ class DewBlock(Block): key_id = key_id, sequence = sequence ) - response = self.dew_client.kms_client.disable_key(request) + response = self.__dew_client.kms_client.disable_key(request) self.logger.info("Successfully disable_key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def enable_key(self, key_id = None, sequence = None, **kwargs): """ Enable the key, which can only be used after it is enabled. Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str + :type key_ Id: str """ try: request = EnableKeyRequest() @@ -171,26 +171,26 @@ class DewBlock(Block): key_id = key_id, sequence = sequence ) - response = self.dew_client.kms_client.enable_key(request) + response = self.__dew_client.kms_client.enable_key(request) self.logger.info("Successfully enable_key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def update_key_Alias(self, key_id = None, key_alias = None, sequence = None, **kwargs): """ Modify the user master key alias Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_ Id: str - :key_alias: Non default master key alias, ranging from 1 to 255 characters, satisfies regular matching + :key_alias: Non default master key alias, ranging from 1 to 255 characters, satisfies regular matching "^[a-zA-Z0-9:/_-]{1,255}$"and cannot have the suffix "/default". - :type key_alias: str - """ + :type key_alias: str + """ try: request = UpdateKeyAliasRequest() request.body = UpdateKeyAliasRequestBody( @@ -198,18 +198,18 @@ class DewBlock(Block): key_id = key_id, sequence = sequence ) - response = self.dew_client.kms_client.update_key_alias(request) + response = self.__dew_client.kms_client.update_key_alias(request) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def update_key_description(self, key_id = None, key_description = None, sequence = None, **kwargs): """ Modify user master key description information. Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_ Id: str :key_description: Key description, ranging from 0 to 255 characters. @@ -222,20 +222,20 @@ class DewBlock(Block): key_description = key_description, sequence = sequence ) - response = self.dew_client.kms_client.update_key_description(request) + response = self.__dew_client.kms_client.update_key_description(request) self.logger.info("Successfully update_key_description:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def cancel_key_deletion(self, key_id = None, sequence = None, **kwargs): """ Cancel plan to delete key. - + Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_ Id: str """ @@ -245,20 +245,20 @@ class DewBlock(Block): key_id = key_id, sequence = sequence ) - response = self.dew_client.kms_client.cancel_key_deletion(request) + response = self.__dew_client.kms_client.cancel_key_deletion(request) self.logger.info("Successfully canccel key daletion:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def create_data_key(self, key_id, key_spec = None, datakey_length = None, sequence = None, **kwargs): """ Create a data key and return a result containing both plaintext and ciphertext. Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_ Id: str """ @@ -270,20 +270,20 @@ class DewBlock(Block): datakey_length = datakey_length, sequence = sequence ) - response = self.dew_client.kms_client.create_datakey(request) + response = self.__dew_client.kms_client.create_datakey(request) self.logger.info("Successfully created datakey:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def create_data_key_without_plaintext(self, key_id, key_spec = None, datakey_length = None, sequence = None, **kwargs): """ - Create a data key and return a result that only contains ciphertext. - + Create a data key and return a result that only contains ciphertext. + Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_ Id: str """ @@ -295,20 +295,20 @@ class DewBlock(Block): datakey_length = datakey_length, sequence = sequence ) - response = self.dew_client.kms_client.create_datakey_without_plaintext(request) + response = self.__dew_client.kms_client.create_datakey_without_plaintext(request) self.logger.info("Successfully created datakey without plaintext:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def create_random(self, random_data_length = None, sequence = None, **kwargs): """ Generate random numbers within the range of 8-8192 bits. Args: - :param random_ Data_ Length: The bit length of a random number. The value is a multiple of 8, with a range of 8 to 8192. + :param random_ Data_ Length: The bit length of a random number. The value is a multiple of 8, with a range of 8 to 8192. The bit length of a random number, with a value of 512. :type random_ Data_ Length: str """ @@ -318,24 +318,24 @@ class DewBlock(Block): random_data_length = random_data_length, sequence = sequence ) - response = self.dew_client.kms_client.create_random(request) + response = self.__dew_client.kms_client.create_random(request) self.logger.info("Successfully created random:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def decrypt_data_key(self, key_id = None, cipher_text = None, datakey_cipher_length = None, sequence = None, **kwargs): """ Decrypt data key, decrypt data key with specified master key. Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_ Id: str - :cipher_text: The hexadecimal string of DEK ciphertext and metadata. + :cipher_text: The hexadecimal string of DEK ciphertext and metadata. The value is the cipher in the encrypted data key result_ The value of text. :type cipher_text: str @@ -350,25 +350,25 @@ class DewBlock(Block): datakey_cipher_length = datakey_cipher_length, sequence = sequence ) - response = self.dew_client.kms_client.decrypt_datakey(request) + response = self.__dew_client.kms_client.decrypt_datakey(request) self.logger.info("Successfully decrypted datakey:") self.logger.info(response) return response - + except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def encrypt_data_key(self, key_id = None, plain_text = None, datakey_plain_length = None, sequence = None, **kwargs): """ Encrypt the data key with the specified master key. - + Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_ Id: str - :param plain_ Text: When CMK is AES, SHA256 (32 bytes) for DEK plaintext and DEK plaintext; When CMK is SM4, + :param plain_ Text: When CMK is AES, SHA256 (32 bytes) for DEK plaintext and DEK plaintext; When CMK is SM4, both DEK plaintext and SM3 (32 bytes) of DEK plaintext are represented as hexadecimal strings. :type plain_ Text: str @@ -383,7 +383,7 @@ class DewBlock(Block): datakey_plain_length = datakey_plain_length, sequence = sequence ) - response = self.dew_client.kms_client.encrypt_datakey(request) + response = self.__dew_client.kms_client.encrypt_datakey(request) self.logger.info("Successfully encrypted datakey:") self.logger.info(response) return response @@ -394,12 +394,12 @@ class DewBlock(Block): def create_parameters_for_import(self, key_id,wrapping_algorithm = None, sequence = None, **kwargs): """ Obtain the necessary parameters for importing keys, including key import tokens and key encryption public keys. - + Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_ Id: str - :wrapping_algorithm: Key material encryption algorithm, enumeration as follows: - RSAES_ OAEP_ SHA_ 256- SM2_ ENCRYPT, + :wrapping_algorithm: Key material encryption algorithm, enumeration as follows: - RSAES_ OAEP_ SHA_ 256- SM2_ ENCRYPT, some offices do not support this import type :type wrapping_ algorithm: str """ @@ -410,20 +410,20 @@ class DewBlock(Block): wrapping_algorithm = wrapping_algorithm, sequence = sequence ) - response = self.dew_client.kms_client.create_parameters_for_import(request) + response = self.__dew_client.kms_client.create_parameters_for_import(request) self.logger.info("Successfully created parameters for import:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def delete_imported_key_material(self, key_id, sequence = None, **kwargs): """ Delete key material information. Args: - :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. + :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_ Id: str """ @@ -433,30 +433,30 @@ class DewBlock(Block): key_id = key_id, sequence = sequence ) - response = self.dew_client.kms_client.delete_imported_key_material(request) + response = self.__dew_client.kms_client.delete_imported_key_material(request) self.logger.info("Successfully deleted imported key material:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - - def import_key_material(self, key_id = None, import_token = None, - encrypted_key_material = None, encrypted_privatekey = None, + + def import_key_material(self, key_id = None, import_token = None, + encrypted_key_material = None, encrypted_privatekey = None, expiration_time = None, sequence = None, **kwargs): """ Import key materials. Args: - : param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + : param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str :param import_token: Key import token, in base64 format, that satisfies regular matching "^[0-9a-zA-Z+/=]{200,6144}$". :type import_ Token: str - :param encrypted_key_material: The encrypted symmetric key material, in base64 format, satisfies regular matching + :param encrypted_key_material: The encrypted symmetric key material, in base64 format, satisfies regular matching "^[0-9a-zA-Z+/=]{344,360}$". If importing an asymmetric key, this parameter is the temporary intermediate key used to encrypt the private key. :type encrypted_key_material: str """ @@ -470,55 +470,55 @@ class DewBlock(Block): expiration_time = expiration_time, sequence = sequence ) - response = self.dew_client.kms_client.import_key_material(request) + response = self.__dew_client.kms_client.import_key_material(request) self.logger.info("Successfully imported key material:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_grant(self, key_id = None, grantee_principal = None, listOperationsbody = None, + + def create_grant(self, key_id = None, grantee_principal = None, listOperationsbody = None, name = None, retiring_principal = None, grantee_principal_type = None, sequence = None, **kwargs): """ Create authorization, authorized users can operate on the authorization key. Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str - :param grantee_principal:Authorized user ID, 1~64 bytes, satisfies regular matching "^[a-zA-Z0-9]{1,64}$". + :param grantee_principal:Authorized user ID, 1~64 bytes, satisfies regular matching "^[a-zA-Z0-9]{1,64}$". For example:0d0466b00d0466b00d0466b00d0466b0 :type grantee_principal: str - :param operations: List of authorized and allowed operations. Valid values: "create datakey", "create datakey without plaintext", - "encrypt datakey", "decrypt datakey", "describe key", "create grant", "retain grant", "encrypt data", "decrypt data". The valid - values cannot be just "create grant"- "Create datakey" Create data key - "Create datakey without plaintext" Create data key without - plaintext - "encrypt datakey" Encrypt data key - "decrypt datakey" Decrypt data key - "describe key" Query key information - + :param operations: List of authorized and allowed operations. Valid values: "create datakey", "create datakey without plaintext", + "encrypt datakey", "decrypt datakey", "describe key", "create grant", "retain grant", "encrypt data", "decrypt data". The valid + values cannot be just "create grant"- "Create datakey" Create data key - "Create datakey without plaintext" Create data key without + plaintext - "encrypt datakey" Encrypt data key - "decrypt datakey" Decrypt data key - "describe key" Query key information - "retain grant" Retirement authorization - "encrypt data" Encrypt data - "decrypt data" Decrypt data :type operations: list[str] """ try: - request = CreateGrantRequest() + request = CreateGrantRequest() request.body = CreateGrantRequestBody( key_id = key_id, - grantee_principal = grantee_principal, + grantee_principal = grantee_principal, operations = listOperationsbody, grantee_principal_type = grantee_principal_type, retiring_principal = retiring_principal, name = name, sequence = sequence ) - response = self.dew_client.kms_client.create_grant(request) + response = self.__dew_client.kms_client.create_grant(request) self.logger.info("Successfully create grant:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def list_retirable_grants(self, limit = None, marker = None, sequence = None, **kwargs): """ Query the list of authorizations that users can retire from. @@ -530,21 +530,21 @@ class DewBlock(Block): marker = marker, sequence = sequence ) - response = self.dew_client.kms_client.list_retirable_grants(request) + response = self.__dew_client.kms_client.list_retirable_grants(request) self.logger.info("Successfully list retirable grants:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def list_grants(self, key_id = None, limit = None, marker = None, sequence = None, **kwargs): """ Authorization list for querying keys - + Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str """ @@ -556,30 +556,30 @@ class DewBlock(Block): marker = marker, sequence = sequence ) - response = self.dew_client.kms_client.list_grants(request) + response = self.__dew_client.kms_client.list_grants(request) self.logger.info("Successfully list grants:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def cancel_self_grant(self, key_id = None, grant_id = None, sequence = None, **kwargs): """ - Retirement authorization means that the authorized user no longer has the right to operate the authorization key. - For example, if user A authorizes user B to operate key A/key, and authorizes user C to revoke the authorization, + Retirement authorization means that the authorized user no longer has the right to operate the authorization key. + For example, if user A authorizes user B to operate key A/key, and authorizes user C to revoke the authorization, then users A, B, and C can all retire the authorization. After retiring the authorization, user B can no longer use key A. Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str - :param grant_id: Authorization ID, 64 bytes, satisfies regular matching "^[A-Fa-f0-9]{64}$". + :param grant_id: Authorization ID, 64 bytes, satisfies regular matching "^[A-Fa-f0-9]{64}$". For example:7c9a3286af4fcca5f0a385ad13e1d21a50e27b6dbcab50f37f30f93b8939827d - :type grant_id: str - """ + :type grant_id: str + """ try: request = CancelSelfGrantRequest() request.body = RevokeGrantRequestBody( @@ -587,27 +587,27 @@ class DewBlock(Block): key_id = key_id, sequence = sequence ) - response = self.dew_client.kms_client.cancel_self_grant(request) + response = self.__dew_client.kms_client.cancel_self_grant(request) self.logger.info("Successfully cancel self grant:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def cancel_grant(self, key_id = None, grant_id = None, sequence = None, **kwargs): """ Revoke authorization, authorize the user to revoke the authorized user's permission to operate the key Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str - :param grant_id: Authorization ID, 64 bytes, satisfies regular matching "^[A-Fa-f0-9]{64}$". + :param grant_id: Authorization ID, 64 bytes, satisfies regular matching "^[A-Fa-f0-9]{64}$". For example:7c9a3286af4fcca5f0a385ad13e1d21a50e27b6dbcab50f37f30f93b8939827d - :type grant_id: str + :type grant_id: str """ try: request = CancelGrantRequest() @@ -616,7 +616,7 @@ class DewBlock(Block): key_id = key_id, sequence = sequence ) - response = self.dew_client.kms_client.cancel_grant(request) + response = self.__dew_client.kms_client.cancel_grant(request) self.logger.info("Successfully cancel grant:") self.logger.info(response) return response @@ -627,9 +627,9 @@ class DewBlock(Block): def decrypt_data(self, cipher_text = None, encryption_algorithm = None, key_id = None, sequence = None, **kwargs): """ Decrypting data. - + Args: - :param cipher_text: Encrypted data ciphertext. The value is the cipher in the encrypted data result. + :param cipher_text: Encrypted data ciphertext. The value is the cipher in the encrypted data result. The value of text satisfies regular matching "^[0-9a-zA-Z+/=]{128,5648}$". :type cipher_text: str @@ -642,25 +642,25 @@ class DewBlock(Block): key_id = key_id, sequence = sequence ) - response = self.dew_client.kms_client.decrypt_data(request) + response = self.__dew_client.kms_client.decrypt_data(request) self.logger.info("Successfully decrypted data:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def encrypt_data(self, key_id = None,plain_text = None, encryption_algorithm = None, sequence = None, **kwargs): """ Encrypt data using the specified user master key. Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str - :param plain_text: Clear text data, 1-4096 bytes, satisfies regular matching + :param plain_text: Clear text data, 1-4096 bytes, satisfies regular matching "^.{14096}$", and the length range after converting to a byte array is 1-4096 bytes.. :type plain_text: str """ @@ -670,29 +670,29 @@ class DewBlock(Block): plain_text = plain_text, key_id = key_id, encryption_algorithm = encryption_algorithm, - sequence = sequence + sequence = sequence ) - response = self.dew_client.kms_client.encrypt_data(request) + response = self.__dew_client.kms_client.encrypt_data(request) self.logger.info("Successfully encrypted data:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def sign(self, asymmetric_key_id = None, message = None, signing_algorithm = None, message_type = None, sequence = None, **kwargs): """ Digitally sign a message or message digest using a private key with an asymmetric key. Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str - :param signing_algorithm: The signature algorithm is listed as follows: - - RSASSA_PSS_SHA_256 - RSASSA_PSS_SHA_384 - RSASSA_PSS_SHA_512 - RSASSA_PKCS1_V1_5_SHA_256 - - RSASSA_PKCS1_V1_5_SHA_384 - RSASSA_PKCS1_V1_5_SHA_512 - ECDSA_SHA_256 - ECDSA_SHA_384 + :param signing_algorithm: The signature algorithm is listed as follows: + - RSASSA_PSS_SHA_256 - RSASSA_PSS_SHA_384 - RSASSA_PSS_SHA_512 - RSASSA_PKCS1_V1_5_SHA_256 + - RSASSA_PKCS1_V1_5_SHA_384 - RSASSA_PKCS1_V1_5_SHA_512 - ECDSA_SHA_256 - ECDSA_SHA_384 - ECDSA_SHA_512 - SM2DSA_SM3 :type signing_algorithm: str @@ -708,28 +708,28 @@ class DewBlock(Block): message_type = message_type, sequence = sequence ) - response = self.dew_client.kms_client.sign(request) + response = self.__dew_client.kms_client.sign(request) self.logger.info("Successfully sign:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def validate_signature(self, asymmetric_key_id = None, message = None, signature = None, signing_algorithm = None, message_type = None, sequence = None, **kwargs): """ Verify the signature of a message or message digest using a public key with an asymmetric key. Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str - - :param signing_algorithm: The signature algorithm is listed as follows: - - RSASSA_PSS_SHA_256 - RSASSA_PSS_SHA_384 - RSASSA_PSS_SHA_512 - RSASSA_PKCS1_V1_5_SHA_256 - - RSASSA_PKCS1_V1_5_SHA_384 - RSASSA_PKCS1_V1_5_SHA_512 - ECDSA_SHA_256 - ECDSA_SHA_384 + + :param signing_algorithm: The signature algorithm is listed as follows: + - RSASSA_PSS_SHA_256 - RSASSA_PSS_SHA_384 - RSASSA_PSS_SHA_512 - RSASSA_PKCS1_V1_5_SHA_256 + - RSASSA_PKCS1_V1_5_SHA_384 - RSASSA_PKCS1_V1_5_SHA_512 - ECDSA_SHA_256 - ECDSA_SHA_384 - ECDSA_SHA_512 - SM2DSA_SM3 :type signing_algorithm: str @@ -749,7 +749,7 @@ class DewBlock(Block): message_type = message_type, sequence = sequence ) - response = self.dew_client.kms_client.validate_signature(request) + response = self.__dew_client.kms_client.validate_signature(request) self.logger.info("Successfully list validate signature:") self.logger.info(response) return response @@ -762,8 +762,8 @@ class DewBlock(Block): Query key details. Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str """ @@ -773,15 +773,15 @@ class DewBlock(Block): key_id = key_id, sequence = sequence ) - response = self.dew_client.kms_client.list_key_detail(request) + response = self.__dew_client.kms_client.list_key_detail(request) self.logger.info("Successfully list key detail:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - - def list_keys(self,limit = None, marker = None, key_state = None, key_spec = None, + + def list_keys(self,limit = None, marker = None, key_state = None, key_spec = None, enterprise_project_id = None, sequence = None, **kwargs): """ Query the list of all user keys. @@ -796,20 +796,20 @@ class DewBlock(Block): enterprise_project_id = enterprise_project_id, sequence = sequence ) - response = self.dew_client.kms_client.list_keys(request) + response = self.__dew_client.kms_client.list_keys(request) self.logger.info(json.dumps(response.to_dict()).replace('}','}\n')) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def show_public_key(self, asymmetric_key_id = None, sequence = None, **kwargs): """ Query public key information for user specified asymmetric keys. - + Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str """ @@ -819,35 +819,35 @@ class DewBlock(Block): key_id = asymmetric_key_id, sequence = sequence ) - response = self.dew_client.kms_client.show_public_key(request) + response = self.__dew_client.kms_client.show_public_key(request) self.logger.info("Successfully show public key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def show_user_instances(self, **kwargs): """ Query the number of instances to obtain the number of user master keys that have already been created by the user """ try: request = ShowUserInstancesRequest() - response = self.dew_client.kms_client.show_user_instances(request) + response = self.__dew_client.kms_client.show_user_instances(request) self.logger.info("Successfully show user instances:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def show_user_quotas(self, **kwargs): """ Query quotas, query the total number of user master key quotas that users can create and current usage information. """ try: request = ShowUserQuotasRequest() - response = self.dew_client.kms_client.show_user_quotas(request) + response = self.__dew_client.kms_client.show_user_quotas(request) self.logger.info("Successfully show user quotas:") self.logger.info(response) return response @@ -865,21 +865,21 @@ class DewBlock(Block): """ try: request = ShowVersionRequest(version_id = version_id) - response = self.dew_client.kms_client.show_version(request) + response = self.__dew_client.kms_client.show_version(request) self.logger.info("Successfully show_version:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def show_versions(self, **kwargs): """ Query API version information list. """ try: request = ShowVersionsRequest() - response = self.dew_client.kms_client.show_versions(request) + response = self.__dew_client.kms_client.show_versions(request) self.logger.info("Successfully show versions:") self.logger.info(response) return response @@ -891,8 +891,8 @@ class DewBlock(Block): Turn off user master key rotation. Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str """ @@ -902,21 +902,21 @@ class DewBlock(Block): key_id = key_id, sequence = sequence ) - response = self.dew_client.kms_client.disable_key_rotation(request) + response = self.__dew_client.kms_client.disable_key_rotation(request) self.logger.info("Successfully disable key rotation:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def enable_key_rotation(self, key_id = None, sequence = None, **kwargs): """ Enable user master key rotation. Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str """ @@ -926,7 +926,7 @@ class DewBlock(Block): key_id = key_id, sequence = sequence ) - response = self.dew_client.kms_client.enable_key_rotation(request) + response = self.__dew_client.kms_client.enable_key_rotation(request) self.logger.info("Successfully enable key rotation:") self.logger.info(response) return response @@ -939,8 +939,8 @@ class DewBlock(Block): Query user master key rotation status Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str """ @@ -950,26 +950,26 @@ class DewBlock(Block): key_id = key_id, sequence = sequence ) - response = self.dew_client.kms_client.show_key_rotation_status(request) + response = self.__dew_client.kms_client.show_key_rotation_status(request) self.logger.info("Successfully show key rotation status:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def update_key_rotation_interval(self, key_id = None, rotation_interval = None, sequence = None, **kwargs): """ Modify the user master key rotation cycle. - + Args: - :param key_id: Key ID, 36 bytes, satisfies regular matching - "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". + :param key_id: Key ID, 36 bytes, satisfies regular matching + "^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$". For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str - :param rotation_interval: Rotation period, an integer with a range of values from 30 to 365. - The cycle range is set based on the frequency of key usage. If the frequency of key usage is high, + :param rotation_interval: Rotation period, an integer with a range of values from 30 to 365. + The cycle range is set based on the frequency of key usage. If the frequency of key usage is high, it is recommended to set it to a short cycle; On the contrary, set it to long cycle. :type rotation_interval: int """ @@ -980,7 +980,7 @@ class DewBlock(Block): key_id = key_id, sequence = sequence ) - response = self.dew_client.kms_client.update_key_rotation_interval(request) + response = self.__dew_client.kms_client.update_key_rotation_interval(request) self.logger.info("Successfully update key rotation interval:") self.logger.info(response) return response @@ -1010,50 +1010,50 @@ class DewBlock(Block): request.body = CreateKeypairRequestBody( keypair = key_pair_body ) - response = self.dew_client.kps_client.create_keypair(request) + response = self.__dew_client.kps_client.create_keypair(request) self.logger.info("Successfully created keypair:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def list_keypairs(self,limit = None, marker = None, **kwargs): """ - Query SSH key pair list. + Query SSH key pair list. """ try: request = ListKeypairsRequest(limit = limit, marker = marker) - response = self.dew_client.kps_client.list_keypairs(request) + response = self.__dew_client.kps_client.list_keypairs(request) self.logger.info("Successfully list keypairs:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def clear_private_key(self, keypair_name = None, **kwargs): """ Clear SSH key pair private key - + Args: :param keypair_name: Key pair name. :type keypair_name: str """ try: request = ClearPrivateKeyRequest(keypair_name = keypair_name) - response = self.dew_client.kps_client.clear_private_key(request) + response = self.__dew_client.kps_client.clear_private_key(request) self.logger.info("Successfully cleared private key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def import_private_key(self, user_id = None, name = None,type = None, kms_key_name = None, private_key = None, **kwargs): """ Import the private key into the specified key pair. - + Args: :param name: The name of the SSH key pair.- The name of a newly created key pair cannot be the same as the name of an existing key pair. - The SSH key pair name consists of English letters, numbers, underscores, and midlines, and the length cannot exceed 64 bytes @@ -1085,14 +1085,14 @@ class DewBlock(Block): user_id = user_id ) request.body = ImportPrivateKeyRequestBody(keypair = key_pair_body) - response = self.dew_client.kps_client.import_private_key(request) + response = self.__dew_client.kps_client.import_private_key(request) self.logger.info("Successfully import_private_key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def list_keypair_detail(self, keypair_name = None, **kwargs): """ Query SSH key pair details @@ -1103,7 +1103,7 @@ class DewBlock(Block): """ try: request = ListKeypairDetailRequest(keypair_name = keypair_name) - response = self.dew_client.kps_client.list_keypair_detail(request) + response = self.__dew_client.kps_client.list_keypair_detail(request) self.logger.info("Successfully list_keypair_detail") self.logger.info(response) return response @@ -1117,14 +1117,14 @@ class DewBlock(Block): """ try: request = ListKeypairsRequest() - response = self.dew_client.kps_client.list_keypairs(request) + response = self.__dew_client.kps_client.list_keypairs(request) self.logger.info("Successfully list private keys:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def update_keypair_description(self, keypair_name = None, description = None, **kwargs): """ Update SSH key pair description. @@ -1146,18 +1146,18 @@ class DewBlock(Block): request.body = UpdateKeypairDescriptionRequestBody( keypair = key_pair_body ) - response = self.dew_client.kps_client.update_keypair_description(request) + response = self.__dew_client.kps_client.update_keypair_description(request) self.logger.info("Successfully update keypair description:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def export_private_key(self, name = None, **kwargs): """ Export the private key of the specified key pair. - + :param name: SSH key pair name. :type name: str """ @@ -1165,14 +1165,14 @@ class DewBlock(Block): request = ExportPrivateKeyRequest() key_pair_body = KeypairBean(name = name) request.body = ExportPrivateKeyRequestBody(keypair = key_pair_body) - response = self.dew_client.kps_client.export_private_key(request) + response = self.__dew_client.kps_client.export_private_key(request) self.logger.info("Successfully exported private key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def delete_keypair(self, keypair_name = None, **kwargs): """ Delete SSH key pair. @@ -1183,18 +1183,18 @@ class DewBlock(Block): """ try: request = DeleteKeypairRequest(keypair_name = keypair_name) - response = self.dew_client.kps_client.delete_keypair(request) + response = self.__dew_client.kps_client.delete_keypair(request) self.logger.info("Successfully deleted keypair") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def associate_keypair(self, keypair_name = None,type = None, key = None,id = None, disable_password = False, port = None, **kwargs): """ - Bind a new SSH key pair to the specified virtual machine (replace or reset, replacement requires providing - the configured SSH key pair private key of the virtual machine; reset does not require providing the SSH key + Bind a new SSH key pair to the specified virtual machine (replace or reset, replacement requires providing + the configured SSH key pair private key of the virtual machine; reset does not require providing the SSH key pair private key of the virtual machine). Args: @@ -1203,11 +1203,11 @@ class DewBlock(Block): :param id: Virtual machine id that needs to bind (replace or reset) SSH key pairs. :type id: str - + :param type: The value is of enumeration type. password or keypair. :type type: str - :param key: - When type is the enumeration value password, key represents the password- When type is the enumeration + :param key: - When type is the enumeration value password, key represents the password- When type is the enumeration value keypair, key represents the private key. :type key: str """ @@ -1224,7 +1224,7 @@ class DewBlock(Block): server = server_body, keypair_name = keypair_name ) - response = self.dew_client.kps_client.associate_keypair(request) + response = self.__dew_client.kps_client.associate_keypair(request) self.logger.info("Successfully associate_keypair:") self.logger.info(response) return response @@ -1232,11 +1232,11 @@ class DewBlock(Block): self.logger.info(id) self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def batch_associate_keypair(self, keypair_name = None, type = None, key = None, id = None, disable_password = None, port = None, **kwargs): """ Batch bind new SSH key pairs to the specified virtual machine. - + Args: :param keypair_name: The name of the SSH key pair :type keypair_name: list[str] @@ -1245,7 +1245,7 @@ class DewBlock(Block): :type id: list[str] """ try: - request = BatchAssociateKeypairRequest() + request = BatchAssociateKeypairRequest() list_batch_keypairs_body = [] if isinstance(keypair_name,list): for s in range(len(keypair_name)): @@ -1278,32 +1278,32 @@ class DewBlock(Block): keypair_name = keypair_name, server = server_satch_keypairs )) - + request.body = BatchAssociateKeypairRequestBody( batch_keypairs = list_batch_keypairs_body ) - response = self.dew_client.kps_client.batch_associate_keypair(request) + response = self.__dew_client.kps_client.batch_associate_keypair(request) self.logger.info("Successfully batch_associate_keypair:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def delete_all_failed_task(self, **kwargs): """ Delete task information that failed the operation. """ try: request = DeleteAllFailedTaskRequest() - response = self.dew_client.kps_client.delete_all_failed_task(request) + response = self.__dew_client.kps_client.delete_all_failed_task(request) self.logger.info("Successfully delete_all_failed_task:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def delete_failed_task(self, task_id, **kwargs): """ Delete failed tasks. @@ -1313,16 +1313,16 @@ class DewBlock(Block): """ try: request = DeleteFailedTaskRequest( - task_id = task_id, + task_id = task_id, ) - response = self.dew_client.kps_client.delete_failed_task(request) + response = self.__dew_client.kps_client.delete_failed_task(request) self.logger.info("Successfully delete_failed_task:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def disassociate_keypair(self, id = None, type = None, key = None, **kwargs): """ Unbind SSH key pairs to the specified virtual machine and restore SSH password login. @@ -1334,14 +1334,14 @@ class DewBlock(Block): auth_server = Auth(type = type, key = key) server_body = DisassociateEcsServerInfo(id = id, auth = auth_server) request.body = DisassociateKeypairRequestBody(server = server_body) - response = self.dew_client.kps_client.disassociate_keypair(request) + response = self.__dew_client.kps_client.disassociate_keypair(request) self.logger.info("Successfully disassociate_keypair:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def list_failed_task(self, limit = None, offset = None, **kwargs): """ Query task information for failed binding, unbinding, and other operations. @@ -1350,62 +1350,62 @@ class DewBlock(Block): request = ListFailedTaskRequest() request.limit = limit request.offset = offset - response = self.dew_client.kps_client.list_failed_task(request) + response = self.__dew_client.kps_client.list_failed_task(request) self.logger.info("Successfully list_failed_task:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def list_keypair_task(self, task_id = None, **kwargs): """ The task returned by the interface based on the SSH key_ ID, query the execution status of the SSH key for the current task. - + Args: :param task_id: task ID :type task_id: str """ try: request = ListKeypairTaskRequest(task_id = task_id) - response = self.dew_client.kps_client.list_keypair_task(request) + response = self.__dew_client.kps_client.list_keypair_task(request) self.logger.info("Successfully list_keypair_task:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def list_running_task(self, limit = None, offset = None, **kwargs): """ - Query the task information being processed. + Query the task information being processed. """ try: request = ListRunningTaskRequest() request.limit = limit request.offset = offset - response = self.dew_client.kps_client.list_running_task(request) + response = self.__dew_client.kps_client.list_running_task(request) self.logger.info("Successfully list_running_task:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_secret(self, name = None, kms_key_id = None, description = None, - secret_binary = None, secret_string = None, secret_type = None, - auto_rotation = None, rotation_period = None, rotation_config = None, + + def create_secret(self, name = None, kms_key_id = None, description = None, + secret_binary = None, secret_string = None, secret_type = None, + auto_rotation = None, rotation_period = None, rotation_config = None, event_subscriptions = None, enterprise_project_id = None, **kwargs): """ Create a new credential and store the credential value in the initial version of the credential. - The credential management service encrypts the credential values and stores them in the version under the credential object. - Each version can be associated with multiple credential version states, which are used to identify the stage in which the credential - version is in. A version without a version state marker is considered deprecated and can be automatically deleted using the credential + The credential management service encrypts the credential values and stores them in the version under the credential object. + Each version can be associated with multiple credential version states, which are used to identify the stage in which the credential + version is in. A version without a version state marker is considered deprecated and can be automatically deleted using the credential management service. The initial version status is marked as SYSCURRENT. Args: - :param name: The name of the credential to be created. Constraint: The value range is 1 to 64 characters, satisfying the regular matching + :param name: The name of the credential to be created. Constraint: The value range is 1 to 64 characters, satisfying the regular matching "^[a-zA-Z0-9_-]{1,64}$". :type name: str """ @@ -1424,14 +1424,14 @@ class DewBlock(Block): event_subscriptions = event_subscriptions, enterprise_project_id = enterprise_project_id ) - response = self.dew_client.cms_client.create_secret(request) + response = self.__dew_client.cms_client.create_secret(request) self.logger.info("Successfully create_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def download_secret_blob(self, secret_name = None, **kwargs): """ Download backup files for specified credentials. @@ -1442,14 +1442,14 @@ class DewBlock(Block): """ try: request = DownloadSecretBlobRequest(secret_name = secret_name) - response = self.dew_client.cms_client.download_secret_blob(request) + response = self.__dew_client.cms_client.download_secret_blob(request) self.logger.info("Successfully download_secret_blob:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def list_secrets(self, limit = None, marker = None, event_name = None, **kwargs): """ Query all credentials created by the current user under this project. @@ -1459,37 +1459,37 @@ class DewBlock(Block): request.limit = limit request.marker = marker request.event_name = event_name - response = self.dew_client.cms_client.list_secrets(request) + response = self.__dew_client.cms_client.list_secrets(request) self.logger.info("Successfully list_secrets:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def show_secret(self, secret_name, **kwargs): """ Query information for specified credentials. - + Args: :param secret_name: The name of the credential. :type secret_name: str """ try: request = ShowSecretRequest(secret_name = secret_name) - response = self.dew_client.cms_client.show_secret(request) + response = self.__dew_client.cms_client.show_secret(request) self.logger.info("Successfully show_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - - def update_secret(self, kms_key_id = None, secret_name = None, description = None, + + def update_secret(self, kms_key_id = None, secret_name = None, description = None, auto_rotation = None, rotation_period = None, listEventSubscriptionsbody = None, **kwargs): """ Update metadata information for specified credentials. - + Args: :param secret_name: The name of the credential. :type secret_name: str @@ -1499,12 +1499,12 @@ class DewBlock(Block): request.body = UpdateSecretRequestBody( event_subscriptions = listEventSubscriptionsbody, description = description, - kms_key_id = kms_key_id, + kms_key_id = kms_key_id, auto_rotation = auto_rotation, rotation_period = rotation_period, ) request.secret_name = secret_name - response = self.dew_client.cms_client.update_secret(request) + response = self.__dew_client.cms_client.update_secret(request) self.logger.info("Successfully update_secret:") self.logger.info(response) @@ -1512,26 +1512,26 @@ class DewBlock(Block): except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_secret_event(self, target_type = None, target_id = None, + + def create_secret_event(self, target_type = None, target_id = None, target_name = None, event_name = None, state = None, event_types = None, **kwargs): """ - Create an event that can be configured on one or more credential objects. When an event is enabled and the - underlying event type is triggered on the credential object, the cloud service will send the corresponding + Create an event that can be configured on one or more credential objects. When an event is enabled and the + underlying event type is triggered on the credential object, the cloud service will send the corresponding event notification to the notification subject specified by the event. Args: - :param name: The name of the newly created event notification. Constraint: The value range is 1 to 64 + :param name: The name of the newly created event notification. Constraint: The value range is 1 to 64 characters, satisfying the regular matching "^ [a-zA-Z0-9_ -] {1,64} $". :type name: str - :param event_types:he basic event list for this event notification, with the following basic event types. - SECRET_ VERSION_ CREATED: Version Creation SECRET_ VERSION_ EXPIRED: Version expired SECRET_ ROTATED: credential + :param event_types:he basic event list for this event notification, with the following basic event types. + SECRET_ VERSION_ CREATED: Version Creation SECRET_ VERSION_ EXPIRED: Version expired SECRET_ ROTATED: credential rotation SECRET_ DELETED: The credential deletion list cannot contain duplicate underlying event types. :type event_types: list[str] - :param state: controls whether an event takes effect. Only the enabled state can trigger the underlying event types + :param state: controls whether an event takes effect. Only the enabled state can trigger the underlying event types included.ENABLED: enable DisaBLED: disable :type state: str @@ -1557,27 +1557,27 @@ class DewBlock(Block): event_types = event_types, name = event_name, ) - response = self.dew_client.cms_client.create_secret_event(request) + response = self.__dew_client.cms_client.create_secret_event(request) self.logger.info("Successfully create_secret_event:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def upload_secret_blob(self, secret_blob=None, **kwargs): """ Restore credential objects by uploading credential backup files. Args: - :param secret_blob: The credential backup file obtained by backing up the specified credential object contains + :param secret_blob: The credential backup file obtained by backing up the specified credential object contains all current credential version information. The backup file is encrypted and encoded, and its content cannot be read directly. :type secret_blob: str """ try: request = UploadSecretBlobRequest() request.body = UploadSecretBlobRequestBody(secret_blob = secret_blob) - response = self.dew_client.cms_client.upload_secret_blob(request) + response = self.__dew_client.cms_client.upload_secret_blob(request) self.logger.info("Successfully upload_secret_blob:") self.logger.info(response) return response @@ -1585,11 +1585,11 @@ class DewBlock(Block): self.logger.error(e.status_code) self.logger.error(e.request_id) self.logger.error(e.error_code) - + def rotate_secret(self,secret_name = None, **kwargs): """ - Immediately execute the rotation of credentials. Create a new credential version within the specified credentials to encrypt - and store randomly generated credential values in the background. At the same time, mark the newly created credential version + Immediately execute the rotation of credentials. Create a new credential version within the specified credentials to encrypt + and store randomly generated credential values in the background. At the same time, mark the newly created credential version as SYSCURRENT status. Args: @@ -1598,14 +1598,14 @@ class DewBlock(Block): """ try: request = RotateSecretRequest(secret_name = secret_name) - response = self.dew_client.cms_client.rotate_secret(request) + response = self.__dew_client.cms_client.rotate_secret(request) self.logger.info("Successfully rotate_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def restore_secret(self,secret_name, **kwargs): """ Cancel the scheduled deletion task of credentials and restore the usable state of the credential object. @@ -1616,14 +1616,14 @@ class DewBlock(Block): """ try: request = RestoreSecretRequest(secret_name = secret_name) - response = self.dew_client.cms_client.restore_secret(request) + response = self.__dew_client.cms_client.restore_secret(request) self.logger.info("Successfully restore_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def delete_secret_for_schedule(self,recovery_window_in_days = None,secret_name = None, **kwargs): """ Specify a delayed deletion time, create a scheduled task to delete credentials, and set a delayed deletion time of 7-30 days. @@ -1632,7 +1632,7 @@ class DewBlock(Block): :param secret_name: The name of the credential. :type secret_name: str - :param recovery_ Window_ In_ Days: Create a task to delete credentials on a scheduled basis, and specify the number of days + :param recovery_ Window_ In_ Days: Create a task to delete credentials on a scheduled basis, and specify the number of days that can be recovered. Constraints: 7-30. Default value: 30. :type recovery_ Window_ In_ Days: int """ @@ -1641,14 +1641,14 @@ class DewBlock(Block): request.body = DeleteSecretForScheduleRequestBody( recovery_window_in_days = recovery_window_in_days ) - response = self.dew_client.cms_client.delete_secret_for_schedule(request) + response = self.__dew_client.cms_client.delete_secret_for_schedule(request) self.logger.info("Successfully delete_secret_for_schedule:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def delete_secret(self,secret_name, **kwargs): """ Immediately delete the specified credentials and cannot recover them. @@ -1659,21 +1659,21 @@ class DewBlock(Block): """ try: request = DeleteSecretRequest(secret_name = secret_name) - response = self.dew_client.cms_client.delete_secret(request) + response = self.__dew_client.cms_client.delete_secret(request) self.logger.info("Successfully delete_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - - def create_secret_version(self,secret_name = None,secret_binary = None, + + def create_secret_version(self,secret_name = None,secret_binary = None, secret_string = None, version_stages = None, expire_time = None, **kwargs): """ - Create a new credential version within the specified credentials to encrypt and store the new credential values. - By default, newly created credential versions are marked as SYSCURRENT, while the previous credential version marked + Create a new credential version within the specified credentials to encrypt and store the new credential values. + By default, newly created credential versions are marked as SYSCURRENT, while the previous credential version marked with SYSCURRENT is marked as SYSPREVIOUS. You can override the default behavior by specifying the Version Stage parameter. - + Args: :param secret_name: The name of the credential. :type secret_name: str @@ -1686,14 +1686,14 @@ class DewBlock(Block): version_stages = version_stages, expire_time = expire_time ) - response = self.dew_client.cms_client.create_secret_version(request) + response = self.__dew_client.cms_client.create_secret_version(request) self.logger.info("Successfully create_secret_version:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def list_secret_versions(self,secret_name = None, marker = None, limit = None, **kwargs): """ Query version list information under specified credentials. @@ -1701,13 +1701,13 @@ class DewBlock(Block): Args: :param secret_name: The name of the credential. :type secret_name: str - """ + """ try: request = ListSecretVersionsRequest() request.secret_name = secret_name request.marker = marker request.limit = limit - response = self.dew_client.cms_client.list_secret_versions(request) + response = self.__dew_client.cms_client.list_secret_versions(request) self.logger.info("Successfully list_secret_versions:") self.logger.info(response) return response @@ -1717,8 +1717,8 @@ class DewBlock(Block): def show_secret_version(self,secret_name = None,version_id = None, **kwargs): """ - Query the information of the specified credential version and the plaintext credential value in the version, - only the credentials with ENABLED status can be queried. The latest version of the credentials can be accessed + Query the information of the specified credential version and the plaintext credential value in the version, + only the credentials with ENABLED status can be queried. The latest version of the credentials can be accessed through/v1/{project_id}/secrets/{secretname}/versions/latest (i.e. assigning {version _id} in the current interface URL as latest) Args: @@ -1732,18 +1732,18 @@ class DewBlock(Block): request = ShowSecretVersionRequest() request.secret_name = secret_name request.version_id = version_id - response = self.dew_client.cms_client.show_secret_version(request) + response = self.__dew_client.cms_client.show_secret_version(request) self.logger.info("Successfully show_secret_version:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def update_version(self,secret_name = None, version_id = None, expire_time = None, **kwargs): """ - Currently, it supports updating the validity period of specified credential versions, and can only update - credentials with ENABLED status. When the event associated with the subscription includes a basic event type + Currently, it supports updating the validity period of specified credential versions, and can only update + credentials with ENABLED status. When the event associated with the subscription includes a basic event type of "version expiration", only one event notification will be triggered after each version expiration update. Args: @@ -1753,8 +1753,8 @@ class DewBlock(Block): :param version_id: The version identifier of the credential. :type version_id: str - :param expire_time: The expiration time of the credential version, timestamp, is the total number of seconds - from January 1, 1970 to that time. The default is empty, and the value used to determine the validity period + :param expire_time: The expiration time of the credential version, timestamp, is the total number of seconds + from January 1, 1970 to that time. The default is empty, and the value used to determine the validity period when subscribing to the "version expiration" event type for credentials. :type expire_time: int """ @@ -1765,14 +1765,14 @@ class DewBlock(Block): request.body = UpdateVersionRequestBody( expire_time = expire_time ) - response = self.dew_client.cms_client.update_version(request) + response = self.__dew_client.cms_client.update_version(request) self.logger.info("Successfully update_version:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def show_secret_stage(self, secret_name=None, stage_name=None, **kwargs): """ Query the version information of the specified credential version status marker. @@ -1786,14 +1786,14 @@ class DewBlock(Block): """ try: request = ShowSecretStageRequest(secret_name=secret_name,stage_name=stage_name) - response = self.dew_client.cms_client.show_secret_stage(request) + response = self.__dew_client.cms_client.show_secret_stage(request) self.logger.info("Successfully show_secret_stage:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def update_secret_stage(self, secret_name = None, stage_name = None, version_id = None, **kwargs): """ Update the version status of credentials. @@ -1808,7 +1808,7 @@ class DewBlock(Block): try: request = UpdateSecretStageRequest(secret_name = secret_name, stage_name = stage_name) request.body = UpdateSecretStageRequestBody(version_id = version_id) - response = self.dew_client.cms_client.update_secret_stage(request) + response = self.__dew_client.cms_client.update_secret_stage(request) self.logger.info("Successfully update_secret_stage:") self.logger.info(response) return response @@ -1829,14 +1829,14 @@ class DewBlock(Block): """ try: request = DeleteSecretStageRequest(secret_name = secret_name, stage_name = stage_name) - response = self.dew_client.cms_client.delete_secret_stage(request) + response = self.__dew_client.cms_client.delete_secret_stage(request) self.logger.info("Successfully delete_secret_stage:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def batch_create_or_delete_tags(self, secret_id = None, key = None, value = None, action = None, sequence = None, **kwargs): """ Batch add or remove credential labels. @@ -1845,8 +1845,8 @@ class DewBlock(Block): :param secret_id: Credential ID :type secret_id: str - :param key: The name of the tag. A label key can only correspond to one label value for the same credential; - Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + :param key: The name of the tag. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: The value range is from 1 to 128 characters, which satisfies regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L} \\\\p{Z}\\\\p{N}_.:=+\\\\-@]*)(?<!\\\\s)$\" :type key: list[str] @@ -1856,12 +1856,12 @@ class DewBlock(Block): """ try: request = BatchCreateOrDeleteTagsRequest(secret_id = secret_id) - - + + listTagsbody = [] if isinstance(key,list): for s in range(len(key)): - listTagsbody.append(TagItem(key =key[s], + listTagsbody.append(TagItem(key =key[s], value = value[s] if value is not None else None)) else: listTagsbody.append(TagItem(key =key, value = value)) @@ -1871,7 +1871,7 @@ class DewBlock(Block): tags=listTagsbody, sequence=sequence ) - response = self.dew_client.cms_client.batch_create_or_delete_tags(request) + response = self.__dew_client.cms_client.batch_create_or_delete_tags(request) self.logger.info("Successfully batch_create_or_delete_tags:") self.logger.info(response) return response @@ -1879,7 +1879,7 @@ class DewBlock(Block): self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - def create_secret_tag(self, secret_id = None, key = None, value = None, **kwargs): + def create_secret_tag(self, secret_id = None, key = None, value = None, **kwargs): """ Add credential labels. @@ -1887,12 +1887,12 @@ class DewBlock(Block): :param secret_id: Credential ID :type secret_id: str - :param key: The name of the tag. A label key can only correspond to one label value for the same credential; - Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + :param key: The name of the tag. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: The value range is from 1 to 128 characters, which satisfies regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L} \\\\p{Z}\\\\p{N}_.:=+\\\\-@]*)(?<!\\\\s)$\" :type key: str - """ + """ try: request = CreateSecretTagRequest(secret_id = secret_id) tagbody = TagItem( @@ -1902,31 +1902,31 @@ class DewBlock(Block): request.body = CreateSecretTagRequestBody( tag=tagbody ) - response = self.dew_client.cms_client.create_secret_tag(request) + response = self.__dew_client.cms_client.create_secret_tag(request) self.logger.info("Successfully create_secret_tag:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def delete_secret_tag(self, secret_id = None, key = None, **kwargs): """ Delete credential labels. - + Args: :param secret_id: Credential ID :type secret_id: str - :param key: The name of the tag. A label key can only correspond to one label value for the same credential; - Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + :param key: The name of the tag. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: The value range is from 1 to 128 characters, which satisfies regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L} \\\\p{Z}\\\\p{N}_.:=+\\\\-@]*)(?<!\\\\s)$\" :type key: str """ try: request = DeleteSecretTagRequest(secret_id = secret_id, key = key) - response = self.dew_client.cms_client.delete_secret_tag(request) + response = self.__dew_client.cms_client.delete_secret_tag(request) self.logger.info("Successfully delete_secret_tag:") self.logger.info(response) return response @@ -1940,7 +1940,7 @@ class DewBlock(Block): """ try: request = ListProjectSecretsTagsRequest() - response = self.dew_client.cms_client.list_project_secrets_tags(request) + response = self.__dew_client.cms_client.list_project_secrets_tags(request) self.logger.info("Successfully list_project_secrets_tags:") self.logger.info(response) return response @@ -1965,7 +1965,7 @@ class DewBlock(Block): listTagsbody = [] if isinstance(key,list): for s in range(len(key)): - listTagsbody.append(Tag(key = key[s] if key is not None else None, + listTagsbody.append(Tag(key = key[s] if key is not None else None, values = values[s] if values is not None else None)) else: listTagsbody.append(Tag(key = key, values = values)) @@ -1977,7 +1977,7 @@ class DewBlock(Block): offset = offset, limit = limit ) - response = self.dew_client.cms_client.list_resource_instances(request) + response = self.__dew_client.cms_client.list_resource_instances(request) self.logger.info("Successfully list_resource_instances:") self.logger.info(response) return response @@ -1988,33 +1988,33 @@ class DewBlock(Block): def list_secret_tags(self, secret_id = None, **kwargs): """ Query credential labels. - + Args: :param secret_id: Credential ID :type secret_id: str """ try: request = ListSecretTagsRequest(secret_id = secret_id) - response = self.dew_client.cms_client.list_secret_tags(request) + response = self.__dew_client.cms_client.list_secret_tags(request) self.logger.info("Successfully list_secret_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") + error_code = {e.error_code}, error_msg = {e.error_msg}") - def delete_secret_event(self, event_name = None, **kwargs): + def delete_secret_event(self, event_name = None, **kwargs): """ - Immediately delete the specified event and cannot be restored. If there is a credential reference in the event, + Immediately delete the specified event and cannot be restored. If there is a credential reference in the event, it cannot be deleted. Please dissociate it first. - + Args: :param event_name: The name of the event notification. :type event_name: str """ try: request = DeleteSecretEventRequest(event_name = event_name) - response = self.dew_client.cms_client.delete_secret_event(request) + response = self.__dew_client.cms_client.delete_secret_event(request) self.logger.info("Successfully delete_secret_event:") self.logger.info(response) return response @@ -2022,15 +2022,15 @@ class DewBlock(Block): self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_secret_events(self, marker = None, limit = None, **kwargs): + def list_secret_events(self, marker = None, limit = None, **kwargs): """ Query all events created by the current user under this project - """ + """ try: request = ListSecretEventsRequest() request.limit =limit request.marker = marker - response = self.dew_client.cms_client.list_secret_events(request) + response = self.__dew_client.cms_client.list_secret_events(request) self.logger.info("Successfully list_secret_events:") self.logger.info(response) return response @@ -2048,7 +2048,7 @@ class DewBlock(Block): """ try: request = ShowSecretEventRequest(event_name = event_name) - response = self.dew_client.cms_client.show_secret_event(request) + response = self.__dew_client.cms_client.show_secret_event(request) self.logger.info("Successfully show_secret_event:") self.logger.info(response) return response @@ -2056,15 +2056,15 @@ class DewBlock(Block): self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - def update_secret_event(self, event_name = None, state = None, event_types = None, notification = None, **kwargs): + def update_secret_event(self, event_name = None, state = None, event_types = None, notification = None, **kwargs): """ - Update metadata information for specified events. The metadata that supports updates includes event enable status, + Update metadata information for specified events. The metadata that supports updates includes event enable status, basic type list, and notification topic. Args: :param event_name: The name of the event notification. :type event_name: str - """ + """ try: request = UpdateSecretEventRequest(event_name = event_name) request.body = UpdateSecretEventRequestBody( @@ -2072,14 +2072,14 @@ class DewBlock(Block): event_types = event_types, notification = notification ) - response = self.dew_client.cms_client.update_secret_event(request) + response = self.__dew_client.cms_client.update_secret_event(request) self.logger.info("Successfully update_secret_event:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def list_notification_records(self, marker = None, limit = None, **kwargs): """ Query triggered event notification records. @@ -2089,17 +2089,17 @@ class DewBlock(Block): limit = limit, marker = marker ) - response = self.dew_client.cms_client.list_notification_records(request) + response = self.__dew_client.cms_client.list_notification_records(request) self.logger.info("Successfully list_notification_records:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def batch_create_kms_tags(self, key_id = None, key = None, value = None, action = None, **kwargs): """ - + Args: :param key_id: key ID :type key_id: str @@ -2107,18 +2107,18 @@ class DewBlock(Block): :param action: Operation identifier: limited to "create" and "delete". :type action: str - :param key: The name of the label. A label key can only correspond to one label value for the same credential; - Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + :param key: The name of the label. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: Value range from 1 to 128 characters, satisfying regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L}\\\\p{Z}\\\\p{N} _.:=+\\\\-@]*)(?<!\\\\s)$\" - :type key: list[str] + :type key: list[str] """ try: request = BatchCreateKmsTagsRequest(key_id = key_id) listTagsbody = [] if isinstance(key,list): for s in range(len(key)): - listTagsbody.append(TagItem(key =key[s], + listTagsbody.append(TagItem(key =key[s], value = value[s] if value is not None else None)) else: listTagsbody.append(TagItem(key =key, value = value)) @@ -2126,14 +2126,14 @@ class DewBlock(Block): action=action, tags=listTagsbody ) - response = self.dew_client.kms_client.batch_create_kms_tags(request) + response = self.__dew_client.kms_client.batch_create_kms_tags(request) self.logger.info("Successfully batch_create_kms_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def create_kms_tag(self, key_id = None, key = None, value = None, **kwargs): """ Add key labels. @@ -2142,12 +2142,12 @@ class DewBlock(Block): :param key_id: key ID :type key_id: str - :param key: The name of the label. A label key can only correspond to one label value for the same credential; - Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: + :param key: The name of the label. A label key can only correspond to one label value for the same credential; + Different credentials can use the same label key. Users can add up to 20 tags to a single credential. Constraint: Value range from 1 to 128 characters, satisfying regular matching\"^((?!\\\\s)(?!_sys_)[\\\\p{L}\\\\p{Z}\\\\p{N} _.:=+\\\\-@]*)(?<!\\\\s)$\" - :type key: str - """ + :type key: str + """ try: request = CreateKmsTagRequest(key_id = key_id) tagbody = TagItem( @@ -2157,29 +2157,29 @@ class DewBlock(Block): request.body = CreateKmsTagRequestBody( tag=tagbody ) - response = self.dew_client.kms_client.create_kms_tag(request) + response = self.__dew_client.kms_client.create_kms_tag(request) self.logger.info("Successfully create_kms_tag:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def list_kms_tags(self, **kwargs): """ Query all label collections of the user under the specified project. """ try: request = ListKmsTagsRequest() - response = self.dew_client.kms_client.list_kms_tags(request) + response = self.__dew_client.kms_client.list_kms_tags(request) self.logger.info("Successfully list_kms_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - - def delete_tag(self, key_id = None, key = None, **kwargs): + + def delete_tag(self, key_id = None, key = None, **kwargs): """ Delete key label. @@ -2191,23 +2191,23 @@ class DewBlock(Block): """ try: request = DeleteTagRequest(key_id = key_id, key = key) - response = self.dew_client.kms_client.delete_tag(request) + response = self.__dew_client.kms_client.delete_tag(request) self.logger.info("Successfully delete_tag:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_kms_by_tags(self,key = None, values = None, limit=None, offset=None, action=None, tags=None, matches=None, sequence=None, **kwargs): + def list_kms_by_tags(self,key = None, values = None, limit=None, offset=None, action=None, tags=None, matches=None, sequence=None, **kwargs): """ Query key instances. Filter through tags to query detailed information about the specified user's master key. - """ + """ try: request = ListKmsByTagsRequest(resource_instances = "resource_instances") listTagsbody = [] if isinstance(key,list): for s in range(len(key)): - listTagsbody.append(Tag(key = key[s] if key is not None else None, + listTagsbody.append(Tag(key = key[s] if key is not None else None, values = values[s] if values is not None else None)) else: listTagsbody.append(Tag(key = key, values = values)) @@ -2219,31 +2219,31 @@ class DewBlock(Block): sequence = sequence, matches = matches ) - response = self.dew_client.kms_client.list_kms_by_tags(request) + response = self.__dew_client.kms_client.list_kms_by_tags(request) self.logger.info("Successfully list_kms_by_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_kms_tags(self, key_id = None, **kwargs): + def show_kms_tags(self, key_id = None, **kwargs): """ Query the key label. - + Args: :param key_id: Key ID :type key_id: str - """ + """ try: request = ShowKmsTagsRequest(key_id = key_id) - response = self.dew_client.kms_client.show_kms_tags(request) + response = self.__dew_client.kms_client.show_kms_tags(request) self.logger.info("Successfully show_kms_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") - + def create_key_store(self, keystore_alias = None, hsm_cluster_id = None, hsm_ca_cert = None, **kwargs): """" @@ -2265,7 +2265,7 @@ class DewBlock(Block): hsm_cluster_id = hsm_cluster_id, keystore_alias = keystore_alias ) - response = self.dew_client.kms_client.create_key_store(request) + response = self.__dew_client.kms_client.create_key_store(request) self.logger.info("Successfully create_key_store:") self.logger.info(response) return response -- Gitee From 0dc3483c5d3065faad47db9508d485a459e6717a Mon Sep 17 00:00:00 2001 From: Lky0312 <523175094@qq.com> Date: Thu, 14 Mar 2024 11:50:04 +0800 Subject: [PATCH 08/11] =?UTF-8?q?=E6=94=B9=E8=BF=9B=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E4=B9=A6=E5=86=99=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefect_huaweicloud/__init__.py | 1 + prefect_huaweicloud/dew_block.py | 1311 ++++++++++++-------- prefect_huaweicloud/test/test_dew_block.py | 469 +++---- 3 files changed, 1021 insertions(+), 760 deletions(-) diff --git a/prefect_huaweicloud/__init__.py b/prefect_huaweicloud/__init__.py index 6710c4a..df80bbb 100644 --- a/prefect_huaweicloud/__init__.py +++ b/prefect_huaweicloud/__init__.py @@ -4,3 +4,4 @@ from prefect_huaweicloud.obs_block import ObsBlock from prefect_huaweicloud.dew_block import DewBlock from prefect_huaweicloud.dew_client import DewClient __all__ = ["ObsBlock","DewBlock","DewClient"] + diff --git a/prefect_huaweicloud/dew_block.py b/prefect_huaweicloud/dew_block.py index 7ae09a4..8201574 100644 --- a/prefect_huaweicloud/dew_block.py +++ b/prefect_huaweicloud/dew_block.py @@ -7,59 +7,229 @@ from prefect.exceptions import MissingContextError from prefect import task from pydantic import VERSION as PYDANTIC_VERSION import json + if PYDANTIC_VERSION.startswith("2."): from pydantic.v1 import Field else: from pydantic import Field from dew_client import DewClient -from huaweicloudsdkkms.v2.model import * +from huaweicloudsdkkms.v2.model import * from huaweicloudsdkcore.exceptions import exceptions from huaweicloudsdkcsms.v1.model import * from huaweicloudsdkkps.v3.model import * +from dataclasses import dataclass class DewBlock(Block): - _logo_url = "https://res-static.hc-cdn.cn/cloudbu-site/public/new-product-icon/SecurityCompliance/DEW.png)" # noqa _block_type_name = "HuaweiCloud DEW" _documentation_url = ("https://support.huaweicloud.com/intl/zh-cn/sdkreference-dew/dew_02_0001.html") # noqa - + huawei_cloud_access_key_id: Optional[SecretStr] = Field( - default = None, - description = "A specific Huawei Cloud access key ID.", - title = "Huawei Cloud Access Key ID:", + default=None, + description="A specific Huawei Cloud access key ID.", + title="Huawei Cloud Access Key ID:", ) huawei_cloud_secret_access_key: Optional[SecretStr] = Field( - default = None, - description = "A specific Huawei Cloud secret access key.", - title = "Huawei Cloud Access Key Secret:", + default=None, + description="A specific Huawei Cloud secret access key.", + title="Huawei Cloud Access Key Secret:", ) huawei_cloud_project_id: Optional[SecretStr] = Field( default=None, - description = "A specific Huawei Cloud project id.", + description="A specific Huawei Cloud project id.", title="Huawei Cloud project id", ) huawei_cloud_security_token: Optional[SecretStr] = Field( - default = None, - description = "SecurityToken in the temporary access key, " + default=None, + description="SecurityToken in the temporary access key, " "You can select a temporary token or AK/SK for authentication", - title = "Huawei Cloud Security Token", + title="Huawei Cloud Security Token", ) - region_id:Optional[str] = Field( - default = None, - title = "region id", + region_id: Optional[str] = Field( + default=None, + title="region id", ) - huawei_cloud_dew_parameters: Optional[Dict[str, Any]] = Field( - default=None, - description="Extra parameters for using dew.", - title="dew_parameters", - ) + huawei_cloud_dew_parameters: Dict = Field( + default=None, + description="Extra parameters for using dew.", + title="dew_parameters", + ) + + @dataclass + class CreateSecretOptions: + def __init__(self,name=None,kms_key_id=None,description=None,secret_binary=None,secret_string=None, + secret_type=None,auto_rotation=None,rotation_period=None,rotation_config=None, + event_subscriptions=None,enterprise_project_id=None): + self.name = Name + self.kms_key_id = kms_key_id + self.description = description + self.secret_binary = secret_binary + self.secret_string = secret_string + self.secret_type = secret_type + self.auto_rotation = auto_rotation + self.rotation_period = rotation_period + self.rotation_config = rotation_config + self.event_subscriptions = event_subscriptions + self.enterprise_project_id = enterprise_project_id + + @dataclass + class CreatekeyOptions: + def __init__(self, key_alias=None, key_spec=None, key_usage=None, key_description=None, + origin=None, enterprise_project_id=None, sequence=None, keystore_id=None): + self.key_alias = key_alias + self.key_spec = key_spec + self.key_usage = key_usage + self.key_description = key_description + self.origin = origin + self.enterprise_project_id = enterprise_project_id + self.sequence = sequence + self.keystore_id = keystore_id + + key_alias=None + key_spec=None + key_usage=None + key_description=None + origin=None + enterprise_project_id=None + sequence=None + keystore_id=None + + @dataclass + class ImportkeyMaterialOptions: + key_id=None + import_token=None + encrypted_key_material=None, + encrypted_privatekey=None + expiration_time=None + sequence=None + + @dataclass + class CreateGrantOptions: + def __init__(self, key_id=None, grantee_principal=None, listOperationsbody=None, name=None, + grantee_principal_type=None, retiring_principal=None, sequence=None): + self.key_id = key_id + self.grantee_principal = grantee_principal + self.listOperationsbody = listOperationsbody + self.name = Name + self.grantee_principal_type = grantee_principal_type + self.retiring_principal = retiring_principal + self.sequence = sequence + + key_id=None + grantee_principal=None + listOperationsbody=None + name=None + retiring_principal=None + grantee_principal_type=None + sequence=None + + @dataclass + class ValidateSignatureOptions: + def __init__(self, asymmetric_key_id=None, message=None, signing_algorithm=None, signature=None, + message_type=None, sequence=None): + self.asymmetric_key_id = asymmetric_key_id + self.message = message + self.signing_algorithm = signing_algorithm + self.signature = signature + self.message_type = message_type + self.sequence = sequence + + @dataclass + class ListKeysOptions: + def __init__(self, limit=None, marker=None, key_state=None, key_spec=None, enterprise_project_id=None, + sequence=None): + self.limit = limit + self.marker = marker + self.key_state = key_state + self.key_spec = key_spec + self.enterprise_project_id = enterprise_project_id + self.sequence = sequence + + @dataclass + class CreateKeypairOptions: + def __init__(self, name=None, type=None, public_key=None, scope=None, user_id=None, key_protection=None): + self.name = Name + self.type = type + self.public_key = public_key + self.scope = scope + self.user_id = user_id + self.key_protection = key_protection + + @dataclass + class AssociateKeypairOptions: + def __init__(self,keypair_name=None,type=None, key=None,id =None,disable_password = False,port=None): + self.keypair_name = keypair_name + self.type = type + self.key = key + self.id = id + self.disable_password = disable_password + self.port = port + + @dataclass + class BatchAssociateKeypairOptions: + def __init__(self,keypair_name=None,type=None, key=None,id=None,disable_password = False,port=None): + self.keypair_name = keypair_name + self.type = type + self.key = key + self.id = id + self.disable_password = disable_password + self.port = port + + @dataclass + class UpdateSecretOptions: + def __init__(self,kms_key_id=None,secret_name=None,description=None,auto_rotation=None, + rotation_period=None,listEventSubscriptionsbody=None): + self.kms_key_id = kms_key_id + self.secret_name = secret_name + self.description = description + self.auto_rotation = auto_rotation + self.rotation_period = rotation_period + self.listEventSubscriptionsbody = listEventSubscriptionsbody + + @dataclass + class CreateSecretEventOptions: + def __init__(self,target_type=None,target_id=None,target_name=None,event_name=None,state=None,event_types=None): + self.target_type = target_type + self.target_id = target_id + self.target_name = target_name + self.event_name = event_name + self.state = state + self.event_types = event_types + + @dataclass + class ListResourceInstancesOptions: + def __init__(self,resource_instances=None,values=None,key=None,limit=None,offset=None,action=None, + matches=None,sequence=None): + self.resource_instances = resource_instances + self.values = values + self.key = key + self.limit = limit + self.offset = offset + self.action = action + self.matches = matches + self.sequence = sequence + + @dataclass + class ListKmsByTagsOptions: + def __init__(self, key=None, values=None, limit=None, offset=None, action=None, tags=None, matches=None, + sequence=None): + self.key = key + self.values = values + self.limit = limit + self.offset = offset + self.action = action + self.tags = tags + self.matches = matches + self.sequence = sequence + def __init__(self, *args, **kwargs): - self.__dew_client = DewClient(region_id = kwargs['region_id'], - ak = kwargs['huawei_cloud_access_key_id'], - sk = kwargs['huawei_cloud_secret_access_key'], - project_id = kwargs['huawei_cloud_project_id'] if kwargs.get('huawei_cloud_project_id') else None) - self.dew_parameters = kwargs['huawei_cloud_dew_parameters'] if kwargs.get('huawei_cloud_project_id') else None + self._dew_client = DewClient(region_id=kwargs.get('region_id'), + ak=kwargs.get('huawei_cloud_access_key_id'), + sk=kwargs.get('huawei_cloud_secret_access_key'), + project_id=kwargs.get('huawei_cloud_project_id')) + self.dew_parameters = kwargs.get('huawei_cloud_dew_parameters') + @property def logger(self) -> Logger: """ @@ -76,13 +246,12 @@ class DewBlock(Block): except MissingContextError: return get_logger(self.__class__.__name__) - def create_key(self, key_alias = None, key_spec = None, key_usage = None, key_description = None, - origin = None, enterprise_project_id = None, sequence = None, keystore_id = None, **kwargs): + def create_key(self, options: CreatekeyOptions): """ Create a user master key, which can be a symmetric or asymmetric key. Args: - Key_ Alias: Non default master key alias, with a value range of 1 to 255 characters, satisfying + key_alias: Non default master key alias, with a value range of 1 to 255 characters, satisfying regular matching "^ [a-zA-Z0-9:/_ -] {1255} $", and not having the same name as the default master key alias created by the system service. type key_alias: str @@ -90,103 +259,107 @@ class DewBlock(Block): try: request = CreateKeyRequest() request.body = CreateKeyRequestBody( - key_alias = key_alias, - key_spec = key_spec, - key_usage = key_usage, - key_description = key_description, - origin = origin, - enterprise_project_id = enterprise_project_id, - sequence = sequence, - keystore_id = keystore_id + key_alias=options.key_alias, + key_spec=options.key_spec, + key_usage=options.key_usage, + key_description=options.key_description, + origin=options.origin, + enterprise_project_id=options.enterprise_project_id, + sequence=options.sequence, + keystore_id=options.keystore_id ) - response = self.__dew_client.kms_client.create_key(request) + response = self._dew_client.kms_client.create_key(request) self.logger.debug("Created key") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def delete_key(self, key_id = None, pending_days = None, sequence = None, **kwargs): + def delete_key(self, key_id=None, pending_days=None, sequence=None): """ How many days do you plan to delete the key? The key can be deleted within 7-1096 days. Args: key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str + :type key_ id: str :pending_days: How many days do you plan to delete the key, with values ranging from 7 to 1096. :type pending_days: str """ try: request = DeleteKeyRequest() request.body = ScheduleKeyDeletionRequestBody( - key_id = key_id, - pending_days = pending_days, - sequence = sequence + key_id=key_id, + pending_days=pending_days, + sequence=sequence ) - response = self.__dew_client.kms_client.delete_key(request) + response = self._dew_client.kms_client.delete_key(request) self.logger.debug("Successfully delete_key") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def disable_key(self, key_id = None, sequence = None, **kwargs): + def disable_key(self, key_id=None, sequence=None): """ Disabled key, cannot be used after disabling the key. Args: :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str + :type key_id: str """ try: request = DisableKeyRequest() request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence + key_id=key_id, + sequence=sequence ) - response = self.__dew_client.kms_client.disable_key(request) + response = self._dew_client.kms_client.disable_key(request) self.logger.info("Successfully disable_key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def enable_key(self, key_id = None, sequence = None, **kwargs): + def enable_key(self, key_id=None, sequence=None): """ Enable the key, which can only be used after it is enabled. Args: :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str + :type key_id: str """ try: request = EnableKeyRequest() request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence + key_id=key_id, + sequence=sequence ) - response = self.__dew_client.kms_client.enable_key(request) + response = self._dew_client.kms_client.enable_key(request) self.logger.info("Successfully enable_key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def update_key_Alias(self, key_id = None, key_alias = None, sequence = None, **kwargs): + def update_key_alias(self, key_id=None, key_alias=None, sequence=None): """ Modify the user master key alias Args: :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str + :type key_id: str :key_alias: Non default master key alias, ranging from 1 to 255 characters, satisfies regular matching "^[a-zA-Z0-9:/_-]{1,255}$"and cannot have the suffix "/default". :type key_alias: str @@ -194,116 +367,121 @@ class DewBlock(Block): try: request = UpdateKeyAliasRequest() request.body = UpdateKeyAliasRequestBody( - key_alias = key_alias, - key_id = key_id, - sequence = sequence + key_alias=key_alias, + key_id=key_id, + sequence=sequence ) - response = self.__dew_client.kms_client.update_key_alias(request) + response = self._dew_client.kms_client.update_key_alias(request) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def update_key_description(self, key_id = None, key_description = None, sequence = None, **kwargs): + def update_key_description(self, key_id=None, key_description=None, sequence=None): """ Modify user master key description information. Args: :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str + :type key_id: str :key_description: Key description, ranging from 0 to 255 characters. :type key_description: str """ try: request = UpdateKeyDescriptionRequest() request.body = UpdateKeyDescriptionRequestBody( - key_id = key_id, - key_description = key_description, - sequence = sequence + key_id=key_id, + key_description=key_description, + sequence=sequence ) - response = self.__dew_client.kms_client.update_key_description(request) + response = self._dew_client.kms_client.update_key_description(request) self.logger.info("Successfully update_key_description:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def cancel_key_deletion(self, key_id = None, sequence = None, **kwargs): + def cancel_key_deletion(self, key_id=None, sequence=None): """ Cancel plan to delete key. Args: :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str + :type key_id: str """ try: request = CancelKeyDeletionRequest() request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence + key_id=key_id, + sequence=sequence ) - response = self.__dew_client.kms_client.cancel_key_deletion(request) + response = self._dew_client.kms_client.cancel_key_deletion(request) self.logger.info("Successfully canccel key daletion:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def create_data_key(self, key_id, key_spec = None, datakey_length = None, sequence = None, **kwargs): + def create_data_key(self, key_id, key_spec=None, datakey_length=None, sequence=None): """ Create a data key and return a result containing both plaintext and ciphertext. Args: :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str + :type key_id: str """ try: request = CreateDatakeyRequest() request.body = CreateDatakeyRequestBody( - key_id = key_id, - key_spec = key_spec, - datakey_length = datakey_length, - sequence = sequence + key_id=key_id, + key_spec=key_spec, + datakey_length=datakey_length, + sequence=sequence ) - response = self.__dew_client.kms_client.create_datakey(request) + response = self._dew_client.kms_client.create_datakey(request) self.logger.info("Successfully created datakey:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def create_data_key_without_plaintext(self, key_id, key_spec = None, datakey_length = None, sequence = None, **kwargs): + def create_data_key_without_plaintext(self, key_id, key_spec=None, datakey_length=None, sequence=None): """ Create a data key and return a result that only contains ciphertext. Args: :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str + :type key_id: str """ try: request = CreateDatakeyWithoutPlaintextRequest() request.body = CreateDatakeyRequestBody( - key_id = key_id, - key_spec = key_spec, - datakey_length = datakey_length, - sequence = sequence + key_id=key_id, + key_spec=key_spec, + datakey_length=datakey_length, + sequence=sequence ) - response = self.__dew_client.kms_client.create_datakey_without_plaintext(request) + response = self._dew_client.kms_client.create_datakey_without_plaintext(request) self.logger.info("Successfully created datakey without plaintext:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def create_random(self, random_data_length = None, sequence = None, **kwargs): + def create_random(self, random_data_length=None, sequence=None): """ Generate random numbers within the range of 8-8192 bits. @@ -315,25 +493,26 @@ class DewBlock(Block): try: request = CreateRandomRequest() request.body = GenRandomRequestBody( - random_data_length = random_data_length, - sequence = sequence + random_data_length=random_data_length, + sequence=sequence ) - response = self.__dew_client.kms_client.create_random(request) + response = self._dew_client.kms_client.create_random(request) self.logger.info("Successfully created random:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def decrypt_data_key(self, key_id = None, cipher_text = None, datakey_cipher_length = None, sequence = None, **kwargs): + def decrypt_data_key(self, key_id=None, cipher_text=None, datakey_cipher_length=None, sequence=None): """ Decrypt data key, decrypt data key with specified master key. Args: :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str + :type key_id: str :cipher_text: The hexadecimal string of DEK ciphertext and metadata. The value is the cipher in the encrypted data key result_ The value of text. @@ -345,12 +524,12 @@ class DewBlock(Block): try: request = DecryptDatakeyRequest() request.body = DecryptDatakeyRequestBody( - key_id = key_id, - cipher_text = cipher_text, - datakey_cipher_length = datakey_cipher_length, - sequence = sequence + key_id=key_id, + cipher_text=cipher_text, + datakey_cipher_length=datakey_cipher_length, + sequence=sequence ) - response = self.__dew_client.kms_client.decrypt_datakey(request) + response = self._dew_client.kms_client.decrypt_datakey(request) self.logger.info("Successfully decrypted datakey:") self.logger.info(response) return response @@ -358,15 +537,16 @@ class DewBlock(Block): except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def encrypt_data_key(self, key_id = None, plain_text = None, datakey_plain_length = None, sequence = None, **kwargs): + def encrypt_data_key(self, key_id=None, plain_text=None, datakey_plain_length=None, sequence=None): """ Encrypt the data key with the specified master key. Args: :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str + :type key_id: str :param plain_ Text: When CMK is AES, SHA256 (32 bytes) for DEK plaintext and DEK plaintext; When CMK is SM4, both DEK plaintext and SM3 (32 bytes) of DEK plaintext are represented as hexadecimal strings. @@ -378,27 +558,28 @@ class DewBlock(Block): try: request = EncryptDatakeyRequest() request.body = EncryptDatakeyRequestBody( - key_id = key_id, - plain_text = plain_text, - datakey_plain_length = datakey_plain_length, - sequence = sequence + key_id=key_id, + plain_text=plain_text, + datakey_plain_length=datakey_plain_length, + sequence=sequence ) - response = self.__dew_client.kms_client.encrypt_datakey(request) + response = self._dew_client.kms_client.encrypt_datakey(request) self.logger.info("Successfully encrypted datakey:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def create_parameters_for_import(self, key_id,wrapping_algorithm = None, sequence = None, **kwargs): + def create_parameters_for_import(self, key_id, wrapping_algorithm=None, sequence=None): """ Obtain the necessary parameters for importing keys, including key import tokens and key encryption public keys. Args: :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str + :type key_id: str :wrapping_algorithm: Key material encryption algorithm, enumeration as follows: - RSAES_ OAEP_ SHA_ 256- SM2_ ENCRYPT, some offices do not support this import type :type wrapping_ algorithm: str @@ -406,44 +587,44 @@ class DewBlock(Block): try: request = CreateParametersForImportRequest() request.body = GetParametersForImportRequestBody( - key_id = key_id, - wrapping_algorithm = wrapping_algorithm, - sequence = sequence + key_id=key_id, + wrapping_algorithm=wrapping_algorithm, + sequence=sequence ) - response = self.__dew_client.kms_client.create_parameters_for_import(request) + response = self._dew_client.kms_client.create_parameters_for_import(request) self.logger.info("Successfully created parameters for import:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def delete_imported_key_material(self, key_id, sequence = None, **kwargs): + def delete_imported_key_material(self, key_id, sequence=None): """ Delete key material information. Args: :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. - :type key_ Id: str + :type key_id: str """ try: request = DeleteImportedKeyMaterialRequest() request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence + key_id=key_id, + sequence=sequence ) - response = self.__dew_client.kms_client.delete_imported_key_material(request) + response = self._dew_client.kms_client.delete_imported_key_material(request) self.logger.info("Successfully deleted imported key material:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def import_key_material(self, key_id = None, import_token = None, - encrypted_key_material = None, encrypted_privatekey = None, - expiration_time = None, sequence = None, **kwargs): + def import_key_material(self, options: ImportkeyMaterialOptions): """ Import key materials. @@ -463,23 +644,23 @@ class DewBlock(Block): try: request = ImportKeyMaterialRequest() request.body = ImportKeyMaterialRequestBody( - key_id = key_id, - import_token = import_token, - encrypted_key_material = encrypted_key_material, - encrypted_privatekey = encrypted_privatekey, - expiration_time = expiration_time, - sequence = sequence + key_id=options.key_id, + import_token=options.import_token, + encrypted_key_material=options.encrypted_key_material, + encrypted_privatekey=options.encrypted_privatekey, + expiration_time=options.expiration_time, + sequence=options.sequence ) - response = self.__dew_client.kms_client.import_key_material(request) + response = self._dew_client.kms_client.import_key_material(request) self.logger.info("Successfully imported key material:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def create_grant(self, key_id = None, grantee_principal = None, listOperationsbody = None, - name = None, retiring_principal = None, grantee_principal_type = None, sequence = None, **kwargs): + def create_grant(self, options: CreateGrantOptions): """ Create authorization, authorized users can operate on the authorization key. @@ -494,51 +675,53 @@ class DewBlock(Block): :type grantee_principal: str :param operations: List of authorized and allowed operations. Valid values: "create datakey", "create datakey without plaintext", - "encrypt datakey", "decrypt datakey", "describe key", "create grant", "retain grant", "encrypt data", "decrypt data". The valid - values cannot be just "create grant"- "Create datakey" Create data key - "Create datakey without plaintext" Create data key without - plaintext - "encrypt datakey" Encrypt data key - "decrypt datakey" Decrypt data key - "describe key" Query key information - - "retain grant" Retirement authorization - "encrypt data" Encrypt data - "decrypt data" Decrypt data + "encrypt-datakey", "decrypt-datakey", "describe-key", "create-grant", "retain grant", "encrypt-data", "decrypt-data". The valid + values cannot be just "create-grant"- "create-datakey" Create data key - "Create datakey without plaintext" Create data key without + plaintext - "encrypt-datakey" Encrypt data key - "decrypt-datakey" Decrypt data key - "describe-key" Query key information - + "retain-grant" Retirement authorization - "encrypt-data" Encrypt data - "decrypt data" Decrypt data :type operations: list[str] """ try: request = CreateGrantRequest() request.body = CreateGrantRequestBody( - key_id = key_id, - grantee_principal = grantee_principal, - operations = listOperationsbody, - grantee_principal_type = grantee_principal_type, - retiring_principal = retiring_principal, - name = name, - sequence = sequence + key_id=options.key_id, + grantee_principal=options.grantee_principal, + operations=options.listOperationsbody, + grantee_principal_type=options.grantee_principal_type, + retiring_principal=options.retiring_principal, + name=options.name, + sequence=options.sequence ) - response = self.__dew_client.kms_client.create_grant(request) + response = self._dew_client.kms_client.create_grant(request) self.logger.info("Successfully create grant:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_retirable_grants(self, limit = None, marker = None, sequence = None, **kwargs): + def list_retirable_grants(self, limit=None, marker=None, sequence=None): """ Query the list of authorizations that users can retire from. """ try: request = ListRetirableGrantsRequest() request.body = ListRetirableGrantsRequestBody( - limit = limit, - marker = marker, - sequence = sequence + limit=limit, + marker=marker, + sequence=sequence ) - response = self.__dew_client.kms_client.list_retirable_grants(request) + response = self._dew_client.kms_client.list_retirable_grants(request) self.logger.info("Successfully list retirable grants:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_grants(self, key_id = None, limit = None, marker = None, sequence = None, **kwargs): + def list_grants(self, key_id=None, limit=None, marker=None, sequence=None): """ Authorization list for querying keys @@ -551,20 +734,21 @@ class DewBlock(Block): try: request = ListGrantsRequest() request.body = ListGrantsRequestBody( - key_id = key_id, - limit = limit, - marker = marker, - sequence = sequence + key_id=key_id, + limit=limit, + marker=marker, + sequence=sequence ) - response = self.__dew_client.kms_client.list_grants(request) + response = self._dew_client.kms_client.list_grants(request) self.logger.info("Successfully list grants:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def cancel_self_grant(self, key_id = None, grant_id = None, sequence = None, **kwargs): + def cancel_self_grant(self, key_id=None, grant_id=None, sequence=None): """ Retirement authorization means that the authorized user no longer has the right to operate the authorization key. For example, if user A authorizes user B to operate key A/key, and authorizes user C to revoke the authorization, @@ -583,19 +767,20 @@ class DewBlock(Block): try: request = CancelSelfGrantRequest() request.body = RevokeGrantRequestBody( - grant_id = grant_id, - key_id = key_id, - sequence = sequence + grant_id=grant_id, + key_id=key_id, + sequence=sequence ) - response = self.__dew_client.kms_client.cancel_self_grant(request) + response = self._dew_client.kms_client.cancel_self_grant(request) self.logger.info("Successfully cancel self grant:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def cancel_grant(self, key_id = None, grant_id = None, sequence = None, **kwargs): + def cancel_grant(self, key_id=None, grant_id=None, sequence=None): """ Revoke authorization, authorize the user to revoke the authorized user's permission to operate the key @@ -612,19 +797,20 @@ class DewBlock(Block): try: request = CancelGrantRequest() request.body = RevokeGrantRequestBody( - grant_id = grant_id, - key_id = key_id, - sequence = sequence + grant_id=grant_id, + key_id=key_id, + sequence=sequence ) - response = self.__dew_client.kms_client.cancel_grant(request) + response = self._dew_client.kms_client.cancel_grant(request) self.logger.info("Successfully cancel grant:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def decrypt_data(self, cipher_text = None, encryption_algorithm = None, key_id = None, sequence = None, **kwargs): + def decrypt_data(self, cipher_text=None, encryption_algorithm=None, key_id=None, sequence=None): """ Decrypting data. @@ -637,20 +823,21 @@ class DewBlock(Block): try: request = DecryptDataRequest() request.body = DecryptDataRequestBody( - cipher_text = cipher_text, - encryption_algorithm = encryption_algorithm, - key_id = key_id, - sequence = sequence + cipher_text=cipher_text, + encryption_algorithm=encryption_algorithm, + key_id=key_id, + sequence=sequence ) - response = self.__dew_client.kms_client.decrypt_data(request) + response = self._dew_client.kms_client.decrypt_data(request) self.logger.info("Successfully decrypted data:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def encrypt_data(self, key_id = None,plain_text = None, encryption_algorithm = None, sequence = None, **kwargs): + def encrypt_data(self, key_id=None, plain_text=None, encryption_algorithm=None, sequence=None): """ Encrypt data using the specified user master key. @@ -667,20 +854,21 @@ class DewBlock(Block): try: request = EncryptDataRequest() request.body = EncryptDataRequestBody( - plain_text = plain_text, - key_id = key_id, - encryption_algorithm = encryption_algorithm, - sequence = sequence + plain_text=plain_text, + key_id=key_id, + encryption_algorithm=encryption_algorithm, + sequence=sequence ) - response = self.__dew_client.kms_client.encrypt_data(request) + response = self._dew_client.kms_client.encrypt_data(request) self.logger.info("Successfully encrypted data:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def sign(self, asymmetric_key_id = None, message = None, signing_algorithm = None, message_type = None, sequence = None, **kwargs): + def sign(self, asymmetric_key_id=None, message=None, signing_algorithm=None, message_type=None, sequence=None): """ Digitally sign a message or message digest using a private key with an asymmetric key. @@ -702,22 +890,22 @@ class DewBlock(Block): try: request = SignRequest() request.body = SignRequestBody( - signing_algorithm = signing_algorithm, - message = message, - key_id = asymmetric_key_id, - message_type = message_type, - sequence = sequence + signing_algorithm=signing_algorithm, + message=message, + key_id=asymmetric_key_id, + message_type=message_type, + sequence=sequence ) - response = self.__dew_client.kms_client.sign(request) + response = self._dew_client.kms_client.sign(request) self.logger.info("Successfully sign:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def validate_signature(self, asymmetric_key_id = None, message = None, signature = None, signing_algorithm = None, - message_type = None, sequence = None, **kwargs): + def validate_signature(self, options: ValidateSignatureOptions): """ Verify the signature of a message or message digest using a public key with an asymmetric key. @@ -742,22 +930,23 @@ class DewBlock(Block): try: request = ValidateSignatureRequest() request.body = VerifyRequestBody( - key_id = asymmetric_key_id, - message = message, - signature = signature, - signing_algorithm = signing_algorithm, - message_type = message_type, - sequence = sequence + key_id=options.asymmetric_key_id, + message=options.message, + signature=options.signature, + signing_algorithm=options.signing_algorithm, + message_type=options.message_type, + sequence=options.sequence ) - response = self.__dew_client.kms_client.validate_signature(request) + response = self._dew_client.kms_client.validate_signature(request) self.logger.info("Successfully list validate signature:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_key_detail(self, key_id = None,sequence = None, **kwargs): + def list_key_detail(self, key_id=None, sequence=None): """ Query key details. @@ -770,40 +959,41 @@ class DewBlock(Block): try: request = ListKeyDetailRequest() request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence + key_id=key_id, + sequence=sequence ) - response = self.__dew_client.kms_client.list_key_detail(request) + response = self._dew_client.kms_client.list_key_detail(request) self.logger.info("Successfully list key detail:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_keys(self,limit = None, marker = None, key_state = None, key_spec = None, - enterprise_project_id = None, sequence = None, **kwargs): + def list_keys(self, options: ListKeysOptions): """ Query the list of all user keys. """ try: request = ListKeysRequest() request.body = ListKeysRequestBody( - limit = limit, - marker = marker, - key_state = key_state, - key_spec = key_spec, - enterprise_project_id = enterprise_project_id, - sequence = sequence + limit=options.limit, + marker=options.marker, + key_state=options.key_state, + key_spec=options.key_spec, + enterprise_project_id=options.enterprise_project_id, + sequence=options.sequence ) - response = self.__dew_client.kms_client.list_keys(request) - self.logger.info(json.dumps(response.to_dict()).replace('}','}\n')) + response = self._dew_client.kms_client.list_keys(request) + self.logger.info(json.dumps(response.to_dict()).replace('}', '}\n')) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def show_public_key(self, asymmetric_key_id = None, sequence = None, **kwargs): + def show_public_key(self, asymmetric_key_id=None, sequence=None): """ Query public key information for user specified asymmetric keys. @@ -816,46 +1006,49 @@ class DewBlock(Block): try: request = ShowPublicKeyRequest() request.body = OperateKeyRequestBody( - key_id = asymmetric_key_id, - sequence = sequence + key_id=asymmetric_key_id, + sequence=sequence ) - response = self.__dew_client.kms_client.show_public_key(request) + response = self._dew_client.kms_client.show_public_key(request) self.logger.info("Successfully show public key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def show_user_instances(self, **kwargs): + def show_user_instances(self): """ Query the number of instances to obtain the number of user master keys that have already been created by the user """ try: request = ShowUserInstancesRequest() - response = self.__dew_client.kms_client.show_user_instances(request) + response = self._dew_client.kms_client.show_user_instances(request) self.logger.info("Successfully show user instances:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def show_user_quotas(self, **kwargs): + def show_user_quotas(self): """ Query quotas, query the total number of user master key quotas that users can create and current usage information. """ try: request = ShowUserQuotasRequest() - response = self.__dew_client.kms_client.show_user_quotas(request) + response = self._dew_client.kms_client.show_user_quotas(request) self.logger.info("Successfully show user quotas:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def show_version(self,version_id = None, **kwargs): + def show_version(self, version_id=None): """ Check the specified API version information @@ -864,29 +1057,32 @@ class DewBlock(Block): :type version_id: str """ try: - request = ShowVersionRequest(version_id = version_id) - response = self.__dew_client.kms_client.show_version(request) + request = ShowVersionRequest(version_id=version_id) + response = self._dew_client.kms_client.show_version(request) self.logger.info("Successfully show_version:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def show_versions(self, **kwargs): + def show_versions(self): """ Query API version information list. """ try: request = ShowVersionsRequest() - response = self.__dew_client.kms_client.show_versions(request) + response = self._dew_client.kms_client.show_versions(request) self.logger.info("Successfully show versions:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(e) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def disable_key_rotation(self, key_id = None, sequence = None, **kwargs): + def disable_key_rotation(self, key_id=None, sequence=None): """ Turn off user master key rotation. @@ -899,18 +1095,19 @@ class DewBlock(Block): try: request = DisableKeyRotationRequest() request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence + key_id=key_id, + sequence=sequence ) - response = self.__dew_client.kms_client.disable_key_rotation(request) + response = self._dew_client.kms_client.disable_key_rotation(request) self.logger.info("Successfully disable key rotation:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def enable_key_rotation(self, key_id = None, sequence = None, **kwargs): + def enable_key_rotation(self, key_id=None, sequence=None): """ Enable user master key rotation. @@ -923,18 +1120,19 @@ class DewBlock(Block): try: request = EnableKeyRotationRequest() request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence + key_id=key_id, + sequence=sequence ) - response = self.__dew_client.kms_client.enable_key_rotation(request) + response = self._dew_client.kms_client.enable_key_rotation(request) self.logger.info("Successfully enable key rotation:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def show_key_rotation_status(self, key_id = None, sequence = None, **kwargs): + def show_key_rotation_status(self, key_id=None, sequence=None): """ Query user master key rotation status @@ -947,18 +1145,19 @@ class DewBlock(Block): try: request = ShowKeyRotationStatusRequest() request.body = OperateKeyRequestBody( - key_id = key_id, - sequence = sequence + key_id=key_id, + sequence=sequence ) - response = self.__dew_client.kms_client.show_key_rotation_status(request) + response = self._dew_client.kms_client.show_key_rotation_status(request) self.logger.info("Successfully show key rotation status:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def update_key_rotation_interval(self, key_id = None, rotation_interval = None, sequence = None, **kwargs): + def update_key_rotation_interval(self, key_id=None, rotation_interval=None, sequence=None): """ Modify the user master key rotation cycle. @@ -976,19 +1175,20 @@ class DewBlock(Block): try: request = UpdateKeyRotationIntervalRequest() request.body = UpdateKeyRotationIntervalRequestBody( - rotation_interval = rotation_interval, - key_id = key_id, - sequence = sequence + rotation_interval=rotation_interval, + key_id=key_id, + sequence=sequence ) - response = self.__dew_client.kms_client.update_key_rotation_interval(request) + response = self._dew_client.kms_client.update_key_rotation_interval(request) self.logger.info("Successfully update key rotation interval:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def create_keypair(self,name = None, type = None, public_key = None, scope = None, user_id = None, key_protection = None, **kwargs): + def create_keypair(self, options: CreateKeypairOptions): """ Create and import SSH key pairs. @@ -1000,39 +1200,41 @@ class DewBlock(Block): try: request = CreateKeypairRequest() key_pair_body = CreateKeypairAction( - name = name, - type = type, - public_key = public_key, - scope = scope, - user_id = user_id, - key_protection = key_protection + name=options.name, + type=options.type, + public_key=options.public_key, + scope=options.scope, + user_id=options.user_id, + key_protection=options.key_protection ) request.body = CreateKeypairRequestBody( - keypair = key_pair_body + keypair=key_pair_body ) - response = self.__dew_client.kps_client.create_keypair(request) + response = self._dew_client.kps_client.create_keypair(request) self.logger.info("Successfully created keypair:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_keypairs(self,limit = None, marker = None, **kwargs): + def list_keypairs(self, limit=None, marker=None): """ Query SSH key pair list. """ try: - request = ListKeypairsRequest(limit = limit, marker = marker) - response = self.__dew_client.kps_client.list_keypairs(request) + request = ListKeypairsRequest(limit=limit, marker=marker) + response = self._dew_client.kps_client.list_keypairs(request) self.logger.info("Successfully list keypairs:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def clear_private_key(self, keypair_name = None, **kwargs): + def clear_private_key(self, keypair_name=None): """ Clear SSH key pair private key @@ -1041,16 +1243,17 @@ class DewBlock(Block): :type keypair_name: str """ try: - request = ClearPrivateKeyRequest(keypair_name = keypair_name) - response = self.__dew_client.kps_client.clear_private_key(request) + request = ClearPrivateKeyRequest(keypair_name=keypair_name) + response = self._dew_client.kps_client.clear_private_key(request) self.logger.info("Successfully cleared private key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def import_private_key(self, user_id = None, name = None,type = None, kms_key_name = None, private_key = None, **kwargs): + def import_private_key(self, user_id=None, name=None, type=None, kms_key_name=None, private_key=None): """ Import the private key into the specified key pair. @@ -1072,28 +1275,29 @@ class DewBlock(Block): try: request = ImportPrivateKeyRequest() encryption_key_protection = Encryption( - type = type, - kms_key_name = kms_key_name + type=type, + kms_key_name=kms_key_name ) key_protection_keypair = ImportPrivateKeyProtection( - private_key = private_key, - encryption = encryption_key_protection + private_key=private_key, + encryption=encryption_key_protection ) - key_pair_body = ImportPrivateKeyKeypairBean( - name = name, - key_protection = key_protection_keypair, - user_id = user_id + key_pair_body = ImportPrivateKeyKeypairBean( + name = Name, + key_protection=key_protection_keypair, + user_id=user_id ) - request.body = ImportPrivateKeyRequestBody(keypair = key_pair_body) - response = self.__dew_client.kps_client.import_private_key(request) + request.body = ImportPrivateKeyRequestBody(keypair=key_pair_body) + response = self._dew_client.kps_client.import_private_key(request) self.logger.info("Successfully import_private_key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_keypair_detail(self, keypair_name = None, **kwargs): + def list_keypair_detail(self, keypair_name=None): """ Query SSH key pair details @@ -1102,30 +1306,17 @@ class DewBlock(Block): :type keypair_name: str """ try: - request = ListKeypairDetailRequest(keypair_name = keypair_name) - response = self.__dew_client.kps_client.list_keypair_detail(request) + request = ListKeypairDetailRequest(keypair_name=keypair_name) + response = self._dew_client.kps_client.list_keypair_detail(request) self.logger.info("Successfully list_keypair_detail") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_keypairs(self, **kwargs): - """ - Query SSH key pair list - """ - try: - request = ListKeypairsRequest() - response = self.__dew_client.kps_client.list_keypairs(request) - self.logger.info("Successfully list private keys:") - self.logger.info(response) - return response - except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - - def update_keypair_description(self, keypair_name = None, description = None, **kwargs): + def update_keypair_description(self, keypair_name=None, description=None): """ Update SSH key pair description. @@ -1138,23 +1329,24 @@ class DewBlock(Block): """ try: request = UpdateKeypairDescriptionRequest( - keypair_name = keypair_name + keypair_name=keypair_name ) key_pair_body = UpdateKeypairDescriptionReq( - description = description + description=description ) request.body = UpdateKeypairDescriptionRequestBody( - keypair = key_pair_body + keypair=key_pair_body ) - response = self.__dew_client.kps_client.update_keypair_description(request) + response = self._dew_client.kps_client.update_keypair_description(request) self.logger.info("Successfully update keypair description:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def export_private_key(self, name = None, **kwargs): + def export_private_key(self, name=None): """ Export the private key of the specified key pair. @@ -1163,17 +1355,18 @@ class DewBlock(Block): """ try: request = ExportPrivateKeyRequest() - key_pair_body = KeypairBean(name = name) - request.body = ExportPrivateKeyRequestBody(keypair = key_pair_body) - response = self.__dew_client.kps_client.export_private_key(request) + key_pair_body = KeypairBean(name = Name) + request.body = ExportPrivateKeyRequestBody(keypair=key_pair_body) + response = self._dew_client.kps_client.export_private_key(request) self.logger.info("Successfully exported private key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def delete_keypair(self, keypair_name = None, **kwargs): + def delete_keypair(self, keypair_name=None): """ Delete SSH key pair. @@ -1182,16 +1375,17 @@ class DewBlock(Block): :type keypair_name: str """ try: - request = DeleteKeypairRequest(keypair_name = keypair_name) - response = self.__dew_client.kps_client.delete_keypair(request) + request = DeleteKeypairRequest(keypair_name=keypair_name) + response = self._dew_client.kps_client.delete_keypair(request) self.logger.info("Successfully deleted keypair") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def associate_keypair(self, keypair_name = None,type = None, key = None,id = None, disable_password = False, port = None, **kwargs): + def associate_keypair(self, options: AssociateKeypairOptions): """ Bind a new SSH key pair to the specified virtual machine (replace or reset, replacement requires providing the configured SSH key pair private key of the virtual machine; reset does not require providing the SSH key @@ -1213,18 +1407,18 @@ class DewBlock(Block): """ try: request = AssociateKeypairRequest() - auth_server = Auth(type = type, key = key) + auth_server = Auth(type=options.type, key=options.key) server_body = EcsServerInfo( - id = id, - auth = auth_server, - disable_password = disable_password, - port = port + auth=auth_server, + id=options.id, + disable_password=options.disable_password, + port=options.port ) request.body = AssociateKeypairRequestBody( - server = server_body, - keypair_name = keypair_name + server=server_body, + keypair_name=options.keypair_name ) - response = self.__dew_client.kps_client.associate_keypair(request) + response = self._dew_client.kps_client.associate_keypair(request) self.logger.info("Successfully associate_keypair:") self.logger.info(response) return response @@ -1232,8 +1426,9 @@ class DewBlock(Block): self.logger.info(id) self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def batch_associate_keypair(self, keypair_name = None, type = None, key = None, id = None, disable_password = None, port = None, **kwargs): + def batch_associate_keypair(self, options: BatchAssociateKeypairOptions): """ Batch bind new SSH key pairs to the specified virtual machine. @@ -1247,64 +1442,67 @@ class DewBlock(Block): try: request = BatchAssociateKeypairRequest() list_batch_keypairs_body = [] - if isinstance(keypair_name,list): - for s in range(len(keypair_name)): + if isinstance(options.keypair_name, list): + for t, k, i, d, p, kn in zip(options.type, options.key, options.id, options.disable_password, + options.port, options.keypair_name): auth_server = Auth( - type = type[s] if type is not None else None, - key = key[s] if key is not None else None + type=t if t is not None else None, + key=k if k is not None else None ) server_satch_keypairs = EcsServerInfo( - id = id[s] if id is not None else None, - auth = auth_server, - disable_password = disable_password[s] if disable_password is not None else None, - port = port[s] if port is not None else None + id=i if i is not None else None, + auth=auth_server, + disable_password=d if d is not None else None, + port=p if p is not None else None ) list_batch_keypairs_body.append(AssociateKeypairRequestBody( - keypair_name = keypair_name[s] if keypair_name is not None else None, - server = server_satch_keypairs + keypair_name=kn if kn is not None else None, + server=server_satch_keypairs )) else: auth_server = Auth( - type = type, - key = key - ) + type=options.type, + key=options.key + ) server_satch_keypairs = EcsServerInfo( - id = id, - auth = auth_server, - disable_password = disable_password, - port = port + id=options.id, + auth=auth_server, + disable_password=options.disable_password, + port=options.port ) list_batch_keypairs_body.append(AssociateKeypairRequestBody( - keypair_name = keypair_name, - server = server_satch_keypairs + keypair_name=options.keypair_name, + server=server_satch_keypairs )) request.body = BatchAssociateKeypairRequestBody( - batch_keypairs = list_batch_keypairs_body + batch_keypairs=list_batch_keypairs_body ) - response = self.__dew_client.kps_client.batch_associate_keypair(request) + response = self._dew_client.kps_client.batch_associate_keypair(request) self.logger.info("Successfully batch_associate_keypair:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def delete_all_failed_task(self, **kwargs): + def delete_all_failed_task(self): """ Delete task information that failed the operation. """ try: request = DeleteAllFailedTaskRequest() - response = self.__dew_client.kps_client.delete_all_failed_task(request) + response = self._dew_client.kps_client.delete_all_failed_task(request) self.logger.info("Successfully delete_all_failed_task:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def delete_failed_task(self, task_id, **kwargs): + def delete_failed_task(self, task_id): """ Delete failed tasks. @@ -1313,17 +1511,18 @@ class DewBlock(Block): """ try: request = DeleteFailedTaskRequest( - task_id = task_id, + task_id=task_id, ) - response = self.__dew_client.kps_client.delete_failed_task(request) + response = self._dew_client.kps_client.delete_failed_task(request) self.logger.info("Successfully delete_failed_task:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def disassociate_keypair(self, id = None, type = None, key = None, **kwargs): + def disassociate_keypair(self, id=None, type=None, key=None): """ Unbind SSH key pairs to the specified virtual machine and restore SSH password login. :param id: Virtual machine ID that needs to bind (replace or reset) SSH key pairs @@ -1331,18 +1530,19 @@ class DewBlock(Block): """ try: request = DisassociateKeypairRequest() - auth_server = Auth(type = type, key = key) - server_body = DisassociateEcsServerInfo(id = id, auth = auth_server) - request.body = DisassociateKeypairRequestBody(server = server_body) - response = self.__dew_client.kps_client.disassociate_keypair(request) + auth_server = Auth(type=type, key=key) + server_body = DisassociateEcsServerInfo(id=id, auth=auth_server) + request.body = DisassociateKeypairRequestBody(server=server_body) + response = self._dew_client.kps_client.disassociate_keypair(request) self.logger.info("Successfully disassociate_keypair:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_failed_task(self, limit = None, offset = None, **kwargs): + def list_failed_task(self, limit=None, offset=None): """ Query task information for failed binding, unbinding, and other operations. """ @@ -1350,15 +1550,16 @@ class DewBlock(Block): request = ListFailedTaskRequest() request.limit = limit request.offset = offset - response = self.__dew_client.kps_client.list_failed_task(request) + response = self._dew_client.kps_client.list_failed_task(request) self.logger.info("Successfully list_failed_task:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_keypair_task(self, task_id = None, **kwargs): + def list_keypair_task(self, task_id=None): """ The task returned by the interface based on the SSH key_ ID, query the execution status of the SSH key for the current task. @@ -1367,16 +1568,17 @@ class DewBlock(Block): :type task_id: str """ try: - request = ListKeypairTaskRequest(task_id = task_id) - response = self.__dew_client.kps_client.list_keypair_task(request) + request = ListKeypairTaskRequest(task_id=task_id) + response = self._dew_client.kps_client.list_keypair_task(request) self.logger.info("Successfully list_keypair_task:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_running_task(self, limit = None, offset = None, **kwargs): + def list_running_task(self, limit=None, offset=None): """ Query the task information being processed. """ @@ -1384,18 +1586,16 @@ class DewBlock(Block): request = ListRunningTaskRequest() request.limit = limit request.offset = offset - response = self.__dew_client.kps_client.list_running_task(request) + response = self._dew_client.kps_client.list_running_task(request) self.logger.info("Successfully list_running_task:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def create_secret(self, name = None, kms_key_id = None, description = None, - secret_binary = None, secret_string = None, secret_type = None, - auto_rotation = None, rotation_period = None, rotation_config = None, - event_subscriptions = None, enterprise_project_id = None, **kwargs): + def create_secret(self, options: CreateSecretOptions): """ Create a new credential and store the credential value in the initial version of the credential. The credential management service encrypts the credential values and stores them in the version under the credential object. @@ -1412,27 +1612,28 @@ class DewBlock(Block): try: request = CreateSecretRequest() request.body = CreateSecretRequestBody( - secret_string = secret_string, - kms_key_id = kms_key_id, - name = name, - description = description, - secret_binary = secret_binary, - secret_type = secret_type, - auto_rotation = auto_rotation, - rotation_period = rotation_period, - rotation_config = rotation_config, - event_subscriptions = event_subscriptions, - enterprise_project_id = enterprise_project_id + secret_string=options.secret_string, + kms_key_id=options.kms_key_id, + name=options.name, + description=options.description, + secret_binary=options.secret_binary, + secret_type=options.secret_type, + auto_rotation=options.auto_rotation, + rotation_period=options.rotation_period, + rotation_config=options.rotation_config, + event_subscriptions=options.event_subscriptions, + enterprise_project_id=options.enterprise_project_id ) - response = self.__dew_client.cms_client.create_secret(request) + response = self._dew_client.cms_client.create_secret(request) self.logger.info("Successfully create_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def download_secret_blob(self, secret_name = None, **kwargs): + def download_secret_blob(self, secret_name=None): """ Download backup files for specified credentials. @@ -1441,16 +1642,17 @@ class DewBlock(Block): :type secret_name: str """ try: - request = DownloadSecretBlobRequest(secret_name = secret_name) - response = self.__dew_client.cms_client.download_secret_blob(request) + request = DownloadSecretBlobRequest(secret_name=secret_name) + response = self._dew_client.cms_client.download_secret_blob(request) self.logger.info("Successfully download_secret_blob:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_secrets(self, limit = None, marker = None, event_name = None, **kwargs): + def list_secrets(self, limit=None, marker=None, event_name=None): """ Query all credentials created by the current user under this project. """ @@ -1459,15 +1661,16 @@ class DewBlock(Block): request.limit = limit request.marker = marker request.event_name = event_name - response = self.__dew_client.cms_client.list_secrets(request) + response = self._dew_client.cms_client.list_secrets(request) self.logger.info("Successfully list_secrets:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def show_secret(self, secret_name, **kwargs): + def show_secret(self, secret_name): """ Query information for specified credentials. @@ -1476,17 +1679,17 @@ class DewBlock(Block): :type secret_name: str """ try: - request = ShowSecretRequest(secret_name = secret_name) - response = self.__dew_client.cms_client.show_secret(request) + request = ShowSecretRequest(secret_name=secret_name) + response = self._dew_client.cms_client.show_secret(request) self.logger.info("Successfully show_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def update_secret(self, kms_key_id = None, secret_name = None, description = None, - auto_rotation = None, rotation_period = None, listEventSubscriptionsbody = None, **kwargs): + def update_secret(self, options: UpdateSecretOptions): """ Update metadata information for specified credentials. @@ -1497,14 +1700,14 @@ class DewBlock(Block): try: request = UpdateSecretRequest() request.body = UpdateSecretRequestBody( - event_subscriptions = listEventSubscriptionsbody, - description = description, - kms_key_id = kms_key_id, - auto_rotation = auto_rotation, - rotation_period = rotation_period, + event_subscriptions=options.listEventSubscriptionsbody, + description=options.description, + kms_key_id=options.kms_key_id, + auto_rotation=options.auto_rotation, + rotation_period=options.rotation_period, ) - request.secret_name = secret_name - response = self.__dew_client.cms_client.update_secret(request) + request.secret_name = options.secret_name + response = self._dew_client.cms_client.update_secret(request) self.logger.info("Successfully update_secret:") self.logger.info(response) @@ -1512,10 +1715,9 @@ class DewBlock(Block): except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def create_secret_event(self, target_type = None, target_id = None, - target_name = None, event_name = None, state = None, - event_types = None, **kwargs): + def create_secret_event(self, options: CreateSecretEventOptions): """ Create an event that can be configured on one or more credential objects. When an event is enabled and the underlying event type is triggered on the credential object, the cloud service will send the corresponding @@ -1538,34 +1740,35 @@ class DewBlock(Block): :param target_ Type: The object type of the event notification. :type target_ Type: str - :param target_ ID: The object ID of the event notification. - :type target_ Id: str + :param target_id: The object ID of the event notification. + :type target_id: str :param target_ Name: The name of the object notified by the event. :type target_ Name: str """ try: request = CreateSecretEventRequest() - notification_body = Notification( - target_type = target_type, - target_id = target_id, - target_name = target_name + notification_body=Notification( + target_type=options.target_type, + target_id=options.target_id, + target_name=options.target_name ) request.body = CreateSecretEventRequestBody( - notification = notification_body, - state = state, - event_types = event_types, - name = event_name, + notification=notification_body, + state=options.state, + event_types=options.event_types, + name=options.event_name, ) - response = self.__dew_client.cms_client.create_secret_event(request) + response = self._dew_client.cms_client.create_secret_event(request) self.logger.info("Successfully create_secret_event:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def upload_secret_blob(self, secret_blob=None, **kwargs): + def upload_secret_blob(self, secret_blob=None): """ Restore credential objects by uploading credential backup files. @@ -1576,17 +1779,17 @@ class DewBlock(Block): """ try: request = UploadSecretBlobRequest() - request.body = UploadSecretBlobRequestBody(secret_blob = secret_blob) - response = self.__dew_client.cms_client.upload_secret_blob(request) + request.body = UploadSecretBlobRequestBody(secret_blob=secret_blob) + response = self._dew_client.cms_client.upload_secret_blob(request) self.logger.info("Successfully upload_secret_blob:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(e.status_code) - self.logger.error(e.request_id) - self.logger.error(e.error_code) + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def rotate_secret(self,secret_name = None, **kwargs): + def rotate_secret(self, secret_name=None): """ Immediately execute the rotation of credentials. Create a new credential version within the specified credentials to encrypt and store randomly generated credential values in the background. At the same time, mark the newly created credential version @@ -1597,16 +1800,17 @@ class DewBlock(Block): :type secret_name: str """ try: - request = RotateSecretRequest(secret_name = secret_name) - response = self.__dew_client.cms_client.rotate_secret(request) + request = RotateSecretRequest(secret_name=secret_name) + response = self._dew_client.cms_client.rotate_secret(request) self.logger.info("Successfully rotate_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def restore_secret(self,secret_name, **kwargs): + def restore_secret(self, secret_name): """ Cancel the scheduled deletion task of credentials and restore the usable state of the credential object. @@ -1615,16 +1819,17 @@ class DewBlock(Block): :type secret_name: str """ try: - request = RestoreSecretRequest(secret_name = secret_name) - response = self.__dew_client.cms_client.restore_secret(request) + request = RestoreSecretRequest(secret_name=secret_name) + response = self._dew_client.cms_client.restore_secret(request) self.logger.info("Successfully restore_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def delete_secret_for_schedule(self,recovery_window_in_days = None,secret_name = None, **kwargs): + def delete_secret_for_schedule(self, recovery_window_in_days=None, secret_name=None): """ Specify a delayed deletion time, create a scheduled task to delete credentials, and set a delayed deletion time of 7-30 days. @@ -1637,19 +1842,20 @@ class DewBlock(Block): :type recovery_ Window_ In_ Days: int """ try: - request = DeleteSecretForScheduleRequest(secret_name = secret_name) + request = DeleteSecretForScheduleRequest(secret_name=secret_name) request.body = DeleteSecretForScheduleRequestBody( - recovery_window_in_days = recovery_window_in_days + recovery_window_in_days=recovery_window_in_days ) - response = self.__dew_client.cms_client.delete_secret_for_schedule(request) + response = self._dew_client.cms_client.delete_secret_for_schedule(request) self.logger.info("Successfully delete_secret_for_schedule:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def delete_secret(self,secret_name, **kwargs): + def delete_secret(self, secret_name): """ Immediately delete the specified credentials and cannot recover them. @@ -1658,17 +1864,18 @@ class DewBlock(Block): :type secret_name: str """ try: - request = DeleteSecretRequest(secret_name = secret_name) - response = self.__dew_client.cms_client.delete_secret(request) + request = DeleteSecretRequest(secret_name=secret_name) + response = self._dew_client.cms_client.delete_secret(request) self.logger.info("Successfully delete_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def create_secret_version(self,secret_name = None,secret_binary = None, - secret_string = None, version_stages = None, expire_time = None, **kwargs): + def create_secret_version(self, secret_name=None, secret_binary=None, + secret_string=None, version_stages=None, expire_time=None): """ Create a new credential version within the specified credentials to encrypt and store the new credential values. By default, newly created credential versions are marked as SYSCURRENT, while the previous credential version marked @@ -1681,20 +1888,21 @@ class DewBlock(Block): try: request = CreateSecretVersionRequest(secret_name=secret_name) request.body = CreateSecretVersionRequestBody( - secret_string = secret_string, - secret_binary = secret_binary, - version_stages = version_stages, - expire_time = expire_time + secret_string=secret_string, + secret_binary=secret_binary, + version_stages=version_stages, + expire_time=expire_time ) - response = self.__dew_client.cms_client.create_secret_version(request) + response = self._dew_client.cms_client.create_secret_version(request) self.logger.info("Successfully create_secret_version:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_secret_versions(self,secret_name = None, marker = None, limit = None, **kwargs): + def list_secret_versions(self, secret_name=None, marker=None, limit=None): """ Query version list information under specified credentials. @@ -1707,15 +1915,16 @@ class DewBlock(Block): request.secret_name = secret_name request.marker = marker request.limit = limit - response = self.__dew_client.cms_client.list_secret_versions(request) + response = self._dew_client.cms_client.list_secret_versions(request) self.logger.info("Successfully list_secret_versions:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def show_secret_version(self,secret_name = None,version_id = None, **kwargs): + def show_secret_version(self, secret_name=None, version_id=None): """ Query the information of the specified credential version and the plaintext credential value in the version, only the credentials with ENABLED status can be queried. The latest version of the credentials can be accessed @@ -1732,15 +1941,16 @@ class DewBlock(Block): request = ShowSecretVersionRequest() request.secret_name = secret_name request.version_id = version_id - response = self.__dew_client.cms_client.show_secret_version(request) + response = self._dew_client.cms_client.show_secret_version(request) self.logger.info("Successfully show_secret_version:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def update_version(self,secret_name = None, version_id = None, expire_time = None, **kwargs): + def update_version(self, secret_name=None, version_id=None, expire_time=None): """ Currently, it supports updating the validity period of specified credential versions, and can only update credentials with ENABLED status. When the event associated with the subscription includes a basic event type @@ -1763,17 +1973,18 @@ class DewBlock(Block): request.version_id = version_id request.secret_name = secret_name request.body = UpdateVersionRequestBody( - expire_time = expire_time + expire_time=expire_time ) - response = self.__dew_client.cms_client.update_version(request) + response = self._dew_client.cms_client.update_version(request) self.logger.info("Successfully update_version:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def show_secret_stage(self, secret_name=None, stage_name=None, **kwargs): + def show_secret_stage(self, secret_name=None, stage_name=None): """ Query the version information of the specified credential version status marker. @@ -1785,16 +1996,17 @@ class DewBlock(Block): :type stage_name: str """ try: - request = ShowSecretStageRequest(secret_name=secret_name,stage_name=stage_name) - response = self.__dew_client.cms_client.show_secret_stage(request) + request = ShowSecretStageRequest(secret_name=secret_name, stage_name=stage_name) + response = self._dew_client.cms_client.show_secret_stage(request) self.logger.info("Successfully show_secret_stage:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def update_secret_stage(self, secret_name = None, stage_name = None, version_id = None, **kwargs): + def update_secret_stage(self, secret_name=None, stage_name=None, version_id=None): """ Update the version status of credentials. @@ -1806,17 +2018,18 @@ class DewBlock(Block): :type stage_name: str """ try: - request = UpdateSecretStageRequest(secret_name = secret_name, stage_name = stage_name) - request.body = UpdateSecretStageRequestBody(version_id = version_id) - response = self.__dew_client.cms_client.update_secret_stage(request) + request = UpdateSecretStageRequest(secret_name=secret_name, stage_name=stage_name) + request.body = UpdateSecretStageRequestBody(version_id=version_id) + response = self._dew_client.cms_client.update_secret_stage(request) self.logger.info("Successfully update_secret_stage:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def delete_secret_stage(self, secret_name = None, stage_name = None, **kwargs): + def delete_secret_stage(self, secret_name=None, stage_name=None): """ Delete the version status of credentials. @@ -1828,16 +2041,17 @@ class DewBlock(Block): :type stage_name: str """ try: - request = DeleteSecretStageRequest(secret_name = secret_name, stage_name = stage_name) - response = self.__dew_client.cms_client.delete_secret_stage(request) + request = DeleteSecretStageRequest(secret_name=secret_name, stage_name=stage_name) + response = self._dew_client.cms_client.delete_secret_stage(request) self.logger.info("Successfully delete_secret_stage:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def batch_create_or_delete_tags(self, secret_id = None, key = None, value = None, action = None, sequence = None, **kwargs): + def batch_create_or_delete_tags(self, secret_id=None, key=None, value=None, action=None, sequence=None): """ Batch add or remove credential labels. @@ -1855,31 +2069,31 @@ class DewBlock(Block): :type action: str """ try: - request = BatchCreateOrDeleteTagsRequest(secret_id = secret_id) - + request = BatchCreateOrDeleteTagsRequest(secret_id=secret_id) listTagsbody = [] - if isinstance(key,list): - for s in range(len(key)): - listTagsbody.append(TagItem(key =key[s], - value = value[s] if value is not None else None)) + if isinstance(key, list): + for k, v in zip(key, value): + listTagsbody.append(TagItem(key=k, + value=v if v is not None else None)) else: - listTagsbody.append(TagItem(key =key, value = value)) + listTagsbody.append(TagItem(key=key, value=value)) request.body = BatchCreateOrDeleteTagsRequestBody( action=action, tags=listTagsbody, sequence=sequence ) - response = self.__dew_client.cms_client.batch_create_or_delete_tags(request) + response = self._dew_client.cms_client.batch_create_or_delete_tags(request) self.logger.info("Successfully batch_create_or_delete_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def create_secret_tag(self, secret_id = None, key = None, value = None, **kwargs): + def create_secret_tag(self, secret_id=None, key=None, value=None): """ Add credential labels. @@ -1894,23 +2108,24 @@ class DewBlock(Block): :type key: str """ try: - request = CreateSecretTagRequest(secret_id = secret_id) + request = CreateSecretTagRequest(secret_id=secret_id) tagbody = TagItem( - key = key, - value = value, + key=key, + value=value, ) request.body = CreateSecretTagRequestBody( tag=tagbody ) - response = self.__dew_client.cms_client.create_secret_tag(request) + response = self._dew_client.cms_client.create_secret_tag(request) self.logger.info("Successfully create_secret_tag:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def delete_secret_tag(self, secret_id = None, key = None, **kwargs): + def delete_secret_tag(self, secret_id=None, key=None): """ Delete credential labels. @@ -1925,30 +2140,32 @@ class DewBlock(Block): :type key: str """ try: - request = DeleteSecretTagRequest(secret_id = secret_id, key = key) - response = self.__dew_client.cms_client.delete_secret_tag(request) + request = DeleteSecretTagRequest(secret_id=secret_id, key=key) + response = self._dew_client.cms_client.delete_secret_tag(request) self.logger.info("Successfully delete_secret_tag:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_project_secrets_tags(self,**kwargs): + def list_project_secrets_tags(self): """ Query the collection of all credential labels for the user under the specified project. """ try: request = ListProjectSecretsTagsRequest() - response = self.__dew_client.cms_client.list_project_secrets_tags(request) + response = self._dew_client.cms_client.list_project_secrets_tags(request) self.logger.info("Successfully list_project_secrets_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_resource_instances(self,resource_instances = None, values = None, key = None, limit = None, offset=None, action = None, matches = None, sequence = None, **kwargs): + def list_resource_instances(self, options: ListResourceInstancesOptions): """ Query credential instances. Filter user credentials through tag filtering and return a list of credentials. @@ -1961,31 +2178,32 @@ class DewBlock(Block): :type resource_instances: str """ try: - request = ListResourceInstancesRequest(resource_instances = resource_instances) + request = ListResourceInstancesRequest(resource_instances=options.resource_instances) listTagsbody = [] - if isinstance(key,list): - for s in range(len(key)): - listTagsbody.append(Tag(key = key[s] if key is not None else None, - values = values[s] if values is not None else None)) + if isinstance(options.key, list): + for k, v in zip(options.key, options.values): + listTagsbody.append(Tag(key=k if k is not None else None, + values=v if v is not None else None)) else: - listTagsbody.append(Tag(key = key, values = values)) + listTagsbody.append(Tag(key=options.key, values=options.values)) request.body = ListResourceInstancesRequestBody( - tags = listTagsbody if key is not None else None, - action = action, - matches = matches, - sequence = sequence, - offset = offset, - limit = limit + tags=listTagsbody if options.key is not None else None, + action=options.action, + matches=options.matches, + sequence=options.sequence, + offset=options.offset, + limit=options.limit ) - response = self.__dew_client.cms_client.list_resource_instances(request) + response = self._dew_client.cms_client.list_resource_instances(request) self.logger.info("Successfully list_resource_instances:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_secret_tags(self, secret_id = None, **kwargs): + def list_secret_tags(self, secret_id=None): """ Query credential labels. @@ -1994,16 +2212,17 @@ class DewBlock(Block): :type secret_id: str """ try: - request = ListSecretTagsRequest(secret_id = secret_id) - response = self.__dew_client.cms_client.list_secret_tags(request) + request = ListSecretTagsRequest(secret_id=secret_id) + response = self._dew_client.cms_client.list_secret_tags(request) self.logger.info("Successfully list_secret_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def delete_secret_event(self, event_name = None, **kwargs): + def delete_secret_event(self, event_name=None): """ Immediately delete the specified event and cannot be restored. If there is a credential reference in the event, it cannot be deleted. Please dissociate it first. @@ -2013,32 +2232,34 @@ class DewBlock(Block): :type event_name: str """ try: - request = DeleteSecretEventRequest(event_name = event_name) - response = self.__dew_client.cms_client.delete_secret_event(request) + request = DeleteSecretEventRequest(event_name=event_name) + response = self._dew_client.cms_client.delete_secret_event(request) self.logger.info("Successfully delete_secret_event:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_secret_events(self, marker = None, limit = None, **kwargs): + def list_secret_events(self, marker=None, limit=None): """ Query all events created by the current user under this project """ try: request = ListSecretEventsRequest() - request.limit =limit + request.limit = limit request.marker = marker - response = self.__dew_client.cms_client.list_secret_events(request) + response = self._dew_client.cms_client.list_secret_events(request) self.logger.info("Successfully list_secret_events:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def show_secret_event(self, event_name = None, **kwargs): + def show_secret_event(self, event_name=None): """ Query information for a specified event. @@ -2047,16 +2268,17 @@ class DewBlock(Block): :type event_name: str """ try: - request = ShowSecretEventRequest(event_name = event_name) - response = self.__dew_client.cms_client.show_secret_event(request) + request = ShowSecretEventRequest(event_name=event_name) + response = self._dew_client.cms_client.show_secret_event(request) self.logger.info("Successfully show_secret_event:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def update_secret_event(self, event_name = None, state = None, event_types = None, notification = None, **kwargs): + def update_secret_event(self, event_name=None, target_type=None, target_id=None, target_name=None): """ Update metadata information for specified events. The metadata that supports updates includes event enable status, basic type list, and notification topic. @@ -2066,38 +2288,43 @@ class DewBlock(Block): :type event_name: str """ try: - request = UpdateSecretEventRequest(event_name = event_name) + request = UpdateSecretEventRequest(event_name=event_name) + notificationbody=Notification( + target_type=target_type, + target_id=target_id, + target_name=target_name + ) request.body = UpdateSecretEventRequestBody( - state = state, - event_types = event_types, - notification = notification + notification=notificationbody ) - response = self.__dew_client.cms_client.update_secret_event(request) + response = self._dew_client.cms_client.update_secret_event(request) self.logger.info("Successfully update_secret_event:") self.logger.info(response) return response except exceptions.ClientRequestException as e: self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_notification_records(self, marker = None, limit = None, **kwargs): + def list_notification_records(self, marker=None, limit=None): """ Query triggered event notification records. """ try: request = ListNotificationRecordsRequest( - limit = limit, - marker = marker + limit=limit, + marker=marker ) - response = self.__dew_client.cms_client.list_notification_records(request) + response = self._dew_client.cms_client.list_notification_records(request) self.logger.info("Successfully list_notification_records:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def batch_create_kms_tags(self, key_id = None, key = None, value = None, action = None, **kwargs): + def batch_create_kms_tags(self, key_id=None, key=None, value=None, action=None): """ Args: @@ -2114,27 +2341,30 @@ class DewBlock(Block): :type key: list[str] """ try: - request = BatchCreateKmsTagsRequest(key_id = key_id) + request = BatchCreateKmsTagsRequest(key_id=key_id) listTagsbody = [] - if isinstance(key,list): - for s in range(len(key)): - listTagsbody.append(TagItem(key =key[s], - value = value[s] if value is not None else None)) + if isinstance(key, list): + if not isinstance(value, list): + value = [value] + for k, v in zip(key, value): + listTagsbody.append(TagItem(key=k, + value=v if v is not None else None)) else: - listTagsbody.append(TagItem(key =key, value = value)) + listTagsbody.append(TagItem(key=key, value=value)) request.body = BatchCreateKmsTagsRequestBody( action=action, tags=listTagsbody ) - response = self.__dew_client.kms_client.batch_create_kms_tags(request) + response = self._dew_client.kms_client.batch_create_kms_tags(request) self.logger.info("Successfully batch_create_kms_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def create_kms_tag(self, key_id = None, key = None, value = None, **kwargs): + def create_kms_tag(self, key_id=None, key=None, value=None): """ Add key labels. @@ -2149,37 +2379,39 @@ class DewBlock(Block): :type key: str """ try: - request = CreateKmsTagRequest(key_id = key_id) + request = CreateKmsTagRequest(key_id=key_id) tagbody = TagItem( - key = key, - value = value + key=key, + value=value ) request.body = CreateKmsTagRequestBody( tag=tagbody ) - response = self.__dew_client.kms_client.create_kms_tag(request) + response = self._dew_client.kms_client.create_kms_tag(request) self.logger.info("Successfully create_kms_tag:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def list_kms_tags(self, **kwargs): + def list_kms_tags(self): """ Query all label collections of the user under the specified project. """ try: request = ListKmsTagsRequest() - response = self.__dew_client.kms_client.list_kms_tags(request) + response = self._dew_client.kms_client.list_kms_tags(request) self.logger.info("Successfully list_kms_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def delete_tag(self, key_id = None, key = None, **kwargs): + def delete_tag(self, key_id=None, key=None): """ Delete key label. @@ -2190,43 +2422,47 @@ class DewBlock(Block): :type key: str """ try: - request = DeleteTagRequest(key_id = key_id, key = key) - response = self.__dew_client.kms_client.delete_tag(request) + request = DeleteTagRequest(key_id=key_id, key=key) + response = self._dew_client.kms_client.delete_tag(request) self.logger.info("Successfully delete_tag:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - def list_kms_by_tags(self,key = None, values = None, limit=None, offset=None, action=None, tags=None, matches=None, sequence=None, **kwargs): + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + return e + + def list_kms_by_tags(self, options: ListKmsByTagsOptions): """ Query key instances. Filter through tags to query detailed information about the specified user's master key. """ try: - request = ListKmsByTagsRequest(resource_instances = "resource_instances") + request = ListKmsByTagsRequest(resource_instances="resource_instances") listTagsbody = [] - if isinstance(key,list): - for s in range(len(key)): - listTagsbody.append(Tag(key = key[s] if key is not None else None, - values = values[s] if values is not None else None)) + if isinstance(options.key, list): + for k, v in zip(options.key, options.values): + listTagsbody.append(Tag(key=k if k is not None else None, + values=v if v is not None else None)) else: - listTagsbody.append(Tag(key = key, values = values)) + listTagsbody.append(Tag(key=options.key, values=options.values)) request.body = ListKmsByTagsRequestBody( - tags = listTagsbody if key is not None else None, - action = action, - offset = offset, - limit = limit, - sequence = sequence, - matches = matches + tags=listTagsbody if options.key is not None else None, + action=options.action, + offset=options.offset, + limit=options.limit, + sequence=options.sequence, + matches=options.matches ) - response = self.__dew_client.kms_client.list_kms_by_tags(request) + response = self._dew_client.kms_client.list_kms_by_tags(request) self.logger.info("Successfully list_kms_by_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - def show_kms_tags(self, key_id = None, **kwargs): + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + return e + + def show_kms_tags(self, key_id=None): """ Query the key label. @@ -2235,17 +2471,17 @@ class DewBlock(Block): :type key_id: str """ try: - request = ShowKmsTagsRequest(key_id = key_id) - response = self.__dew_client.kms_client.show_kms_tags(request) + request = ShowKmsTagsRequest(key_id=key_id) + response = self._dew_client.kms_client.show_kms_tags(request) self.logger.info("Successfully show_kms_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") - + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + return e - def create_key_store(self, keystore_alias = None, hsm_cluster_id = None, hsm_ca_cert = None, **kwargs): + def create_key_store(self, keystore_alias=None, hsm_cluster_id=None, hsm_ca_cert=None): """" Create a tenant exclusive key repository that uses DHSM instances as key storage. @@ -2261,14 +2497,15 @@ class DewBlock(Block): try: request = CreateKeyStoreRequest() request.body = CreateKeyStoreRequestBody( - hsm_ca_cert = hsm_ca_cert, - hsm_cluster_id = hsm_cluster_id, - keystore_alias = keystore_alias + hsm_ca_cert=hsm_ca_cert, + hsm_cluster_id=hsm_cluster_id, + keystore_alias=keystore_alias ) - response = self.__dew_client.kms_client.create_key_store(request) + response = self._dew_client.kms_client.create_key_store(request) self.logger.info("Successfully create_key_store:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ - error_code = {e.error_code}, error_msg = {e.error_msg}") \ No newline at end of file + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + error_code = {e.error_code}, error_msg = {e.error_msg}") + return e diff --git a/prefect_huaweicloud/test/test_dew_block.py b/prefect_huaweicloud/test/test_dew_block.py index bf90810..2c218a9 100644 --- a/prefect_huaweicloud/test/test_dew_block.py +++ b/prefect_huaweicloud/test/test_dew_block.py @@ -2,295 +2,318 @@ import sys from pathlib import Path sys.path.append(str(Path(__file__).resolve().parents[1])) from dew_block import DewBlock -from prefect import flow,task -def kms_params(huaweicloud_dew_block): +from prefect import flow +def kms_parameters(): test_key = None key_alias = None if "key_alias" in huaweicloud_dew_block.dew_parameters: key_alias = huaweicloud_dew_block.dew_parameters["key_alias"] - test_key = huaweicloud_dew_block.create_key(key_alias = key_alias) + test_key = huaweicloud_dew_block.create_key(DewBlock.CreatekeyOptions( key_alias = key_alias)) return dict( - key_alias = key_alias if key_alias is not None else None, - key_id = test_key.key_info.key_id if test_key is not None else None, - key_description = None, - pending_days = huaweicloud_dew_block.dew_parameters["pending_days"] if "pending_days" in huaweicloud_dew_block.dew_parameters else None, - - random_data_length = huaweicloud_dew_block.dew_parameters["random_data_length"] if "random_data_length" in huaweicloud_dew_block.dew_parameters else None, - datakey_length = huaweicloud_dew_block.dew_parameters["datakey_length"] if "datakey_length" in huaweicloud_dew_block.dew_parameters else None, - datakey_plain_length = huaweicloud_dew_block.dew_parameters["datakey_plain_length"] if "datakey_plain_length" in huaweicloud_dew_block.dew_parameters else None, - datakey_cipher_length = huaweicloud_dew_block.dew_parameters["datakey_cipher_length"] if "datakey_cipher_length" in huaweicloud_dew_block.dew_parameters else None, - cipher_text = None, - plain_text = None, - datakey_dgst = None, - - asymmetric_key_id=huaweicloud_dew_block.dew_parameters["asymmetric_key_id"] if "asymmetric_key_id" in huaweicloud_dew_block.dew_parameters else None, - - grantee_principal = huaweicloud_dew_block.dew_parameters["grantee_principal"] if "grantee_principal" in huaweicloud_dew_block.dew_parameters else None, - listOperationsbody = huaweicloud_dew_block.dew_parameters["listOperationsbody"] if "listOperationsbody" in huaweicloud_dew_block.dew_parameters else None, - grant_id = None, - - rotation_interval = huaweicloud_dew_block.dew_parameters["rotation_interval"] if "rotation_interval" in huaweicloud_dew_block.dew_parameters else None, - - signing_algorithm = huaweicloud_dew_block.dew_parameters["signing_algorithm"] if "signing_algorithm" in huaweicloud_dew_block.dew_parameters else None, - message = huaweicloud_dew_block.dew_parameters["message"] if "message" in huaweicloud_dew_block.dew_parameters else None, - message_type = huaweicloud_dew_block.dew_parameters["message_type"] if "message_type" in huaweicloud_dew_block.dew_parameters else None, - signature = None, - - action = huaweicloud_dew_block.dew_parameters["action"] if "action" in huaweicloud_dew_block.dew_parameters else None, - key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, - version_id = huaweicloud_dew_block.dew_parameters["version_id"] if "version_id" in huaweicloud_dew_block.dew_parameters else None, + key_alias = key_alias if key_alias is not None else None, + key_id = test_key.key_info.key_id if test_key is not None else None, + key_description = None, + pending_days = huaweicloud_dew_block.dew_parameters["pending_days"] if "pending_days" in huaweicloud_dew_block.dew_parameters else None, + + random_data_length = huaweicloud_dew_block.dew_parameters["random_data_length"] if "random_data_length" in huaweicloud_dew_block.dew_parameters else None, + datakey_length = huaweicloud_dew_block.dew_parameters["datakey_length"] if "datakey_length" in huaweicloud_dew_block.dew_parameters else None, + datakey_plain_length = huaweicloud_dew_block.dew_parameters["datakey_plain_length"] if "datakey_plain_length" in huaweicloud_dew_block.dew_parameters else None, + datakey_cipher_length = huaweicloud_dew_block.dew_parameters["datakey_cipher_length"] if "datakey_cipher_length" in huaweicloud_dew_block.dew_parameters else None, + cipher_text = None, + plain_text = None, + datakey_dgst = None, + + asymmetric_key_id = huaweicloud_dew_block.dew_parameters["asymmetric_key_id"] if "asymmetric_key_id" in huaweicloud_dew_block.dew_parameters else None, + + grantee_principal = huaweicloud_dew_block.dew_parameters["grantee_principal"] if "grantee_principal" in huaweicloud_dew_block.dew_parameters else None, + listOperationsbody = huaweicloud_dew_block.dew_parameters["listOperationsbody"] if "listOperationsbody" in huaweicloud_dew_block.dew_parameters else None, + grant_id = None, + + rotation_interval = huaweicloud_dew_block.dew_parameters["rotation_interval"] if "rotation_interval" in huaweicloud_dew_block.dew_parameters else None, + + signing_algorithm = huaweicloud_dew_block.dew_parameters["signing_algorithm"] if "signing_algorithm" in huaweicloud_dew_block.dew_parameters else None, + message = huaweicloud_dew_block.dew_parameters["message"] if "message" in huaweicloud_dew_block.dew_parameters else None, + message_type = huaweicloud_dew_block.dew_parameters["message_type"] if "message_type" in huaweicloud_dew_block.dew_parameters else None, + signature = None, + + action = huaweicloud_dew_block.dew_parameters["action"] if "action" in huaweicloud_dew_block.dew_parameters else None, + key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, + version_id = huaweicloud_dew_block.dew_parameters["version_id"] if "version_id" in huaweicloud_dew_block.dew_parameters else None, ) -def kps_params(huaweicloud_dew_block): +def kps_parameters(): key_pair_list = huaweicloud_dew_block.list_keypairs() test_key = None name = None if "name" in huaweicloud_dew_block.dew_parameters: - name = huaweicloud_dew_block.dew_parameters["name"] + name = huaweicloud_dew_block.dew_parameters.get("name") if name in list(x.keypair.name for x in key_pair_list.keypairs[:]): huaweicloud_dew_block.delete_keypair(keypair_name = name) - test_key = huaweicloud_dew_block.create_keypair(name = name) + test_key = huaweicloud_dew_block.create_keypair(DewBlock.CreateKeypairOptions(name = name)) return dict( - name = name, - keypair_name = name, - private_key = test_key.keypair.private_key, - description = None, - id = huaweicloud_dew_block.dew_parameters["id"] if "id" in huaweicloud_dew_block.dew_parameters else None, - kms_key_name = huaweicloud_dew_block.dew_parameters["kms_key_name"] if "kms_key_name" in huaweicloud_dew_block.dew_parameters else None, - type = huaweicloud_dew_block.dew_parameters["type"] if "type" in huaweicloud_dew_block.dew_parameters else None, - key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, - task_id = None, - disable_password = huaweicloud_dew_block.dew_parameters["disable_password"] if "disable_password" in huaweicloud_dew_block.dew_parameters else None, + name = name, + keypair_name = name, + private_key = test_key.keypair.private_key, + description = None, + id = huaweicloud_dew_block.dew_parameters["id"] if "id" in huaweicloud_dew_block.dew_parameters else None, + kms_key_name = huaweicloud_dew_block.dew_parameters["kms_key_name"] if "kms_key_name" in huaweicloud_dew_block.dew_parameters else None, + type = huaweicloud_dew_block.dew_parameters["type"] if "type" in huaweicloud_dew_block.dew_parameters else None, + key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, + task_id = None, + disable_password = huaweicloud_dew_block.dew_parameters["disable_password"] if "disable_password" in huaweicloud_dew_block.dew_parameters else None, ) -def csms_params(huaweicloud_dew_block): +def csms_parameters(): secret_list = huaweicloud_dew_block.list_secrets() secret_string = None event_name = None test_secret = None if "name" and "secret_string" in huaweicloud_dew_block.dew_parameters: - name = huaweicloud_dew_block.dew_parameters["name"] + name = huaweicloud_dew_block.dew_parameters.get("name") secret_string = huaweicloud_dew_block.dew_parameters["secret_string"] if name in list(x.name for x in secret_list.secrets[:]): huaweicloud_dew_block.delete_secret(secret_name = name) - test_secret = huaweicloud_dew_block.create_secret(name,secret_string = secret_string) + test_secret = huaweicloud_dew_block.create_secret(DewBlock.CreateSecretOptions(name = name, secret_string = secret_string)) secret_event = huaweicloud_dew_block.list_secret_events() if event_name in list(x.name for x in secret_event.events[:]): huaweicloud_dew_block.delete_secret_event(event_name = event_name) return dict( - secret_name = test_secret.secret.name, - version_id = huaweicloud_dew_block.dew_parameters["version_id"] if "version_id" in huaweicloud_dew_block.dew_parameters else None, - secret_blob = None, - expire_time = huaweicloud_dew_block.dew_parameters["expire_time"] if "expire_time" in huaweicloud_dew_block.dew_parameters else None, - secret_string = secret_string, - stage_name = huaweicloud_dew_block.dew_parameters["stage_name"] if "stage_name" in huaweicloud_dew_block.dew_parameters else None, - update_stage_name=huaweicloud_dew_block.dew_parameters["update_stage_name"] if "update_stage_name" in huaweicloud_dew_block.dew_parameters else None, - update_version_id = huaweicloud_dew_block.dew_parameters["update_version_id"] if "update_version_id" in huaweicloud_dew_block.dew_parameters else None, - secret_id = test_secret.secret.id, - key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, - action = huaweicloud_dew_block.dew_parameters["action0"] if "action0" in huaweicloud_dew_block.dew_parameters else None, - action1=huaweicloud_dew_block.dew_parameters["action1"] if "action1" in huaweicloud_dew_block.dew_parameters else None, - - value = huaweicloud_dew_block.dew_parameters["value"] if "value" in huaweicloud_dew_block.dew_parameters else None, - values = huaweicloud_dew_block.dew_parameters["values"] if "values" in huaweicloud_dew_block.dew_parameters else None, - resource_instances = huaweicloud_dew_block.dew_parameters["resource_instances"] if "resource_instances" in huaweicloud_dew_block.dew_parameters else None, - event_name = huaweicloud_dew_block.dew_parameters["event_name"] if "event_name" in huaweicloud_dew_block.dew_parameters else None, - event_types = huaweicloud_dew_block.dew_parameters["event_types"] if "event_types" in huaweicloud_dew_block.dew_parameters else None, - state = huaweicloud_dew_block.dew_parameters["state"] if "state" in huaweicloud_dew_block.dew_parameters else None, - target_type = huaweicloud_dew_block.dew_parameters["target_type"] if "target_type" in huaweicloud_dew_block.dew_parameters else None, - target_id = huaweicloud_dew_block.dew_parameters["target_id"] if "target_id" in huaweicloud_dew_block.dew_parameters else None, - target_name = huaweicloud_dew_block.dew_parameters["target_name"] if "target_name" in huaweicloud_dew_block.dew_parameters else None, - recovery_window_in_days = huaweicloud_dew_block.dew_parameters["recovery_window_in_days"] if "recovery_window_in_days" in huaweicloud_dew_block.dew_parameters else None, + secret_name = test_secret.secret.name, + version_id = huaweicloud_dew_block.dew_parameters["version_id"] if "version_id" in huaweicloud_dew_block.dew_parameters else None, + secret_blob = None, + expire_time = huaweicloud_dew_block.dew_parameters["expire_time"] if "expire_time" in huaweicloud_dew_block.dew_parameters else None, + secret_string = secret_string, + stage_name = huaweicloud_dew_block.dew_parameters["stage_name"] if "stage_name" in huaweicloud_dew_block.dew_parameters else None, + update_stage_name = huaweicloud_dew_block.dew_parameters["update_stage_name"] if "update_stage_name" in huaweicloud_dew_block.dew_parameters else None, + update_version_id = huaweicloud_dew_block.dew_parameters["update_version_id"] if "update_version_id" in huaweicloud_dew_block.dew_parameters else None, + secret_id = test_secret.secret.id, + key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, + action = huaweicloud_dew_block.dew_parameters["action0"] if "action0" in huaweicloud_dew_block.dew_parameters else None, + action1 = huaweicloud_dew_block.dew_parameters["action1"] if "action1" in huaweicloud_dew_block.dew_parameters else None, + + value = huaweicloud_dew_block.dew_parameters["value"] if "value" in huaweicloud_dew_block.dew_parameters else None, + values = huaweicloud_dew_block.dew_parameters["values"] if "values" in huaweicloud_dew_block.dew_parameters else None, + resource_instances = huaweicloud_dew_block.dew_parameters["resource_instances"] if "resource_instances" in huaweicloud_dew_block.dew_parameters else None, + event_name = huaweicloud_dew_block.dew_parameters["event_name"] if "event_name" in huaweicloud_dew_block.dew_parameters else None, + event_types = huaweicloud_dew_block.dew_parameters["event_types"] if "event_types" in huaweicloud_dew_block.dew_parameters else None, + state = huaweicloud_dew_block.dew_parameters["state"] if "state" in huaweicloud_dew_block.dew_parameters else None, + target_type = huaweicloud_dew_block.dew_parameters["target_type"] if "target_type" in huaweicloud_dew_block.dew_parameters else None, + target_id = huaweicloud_dew_block.dew_parameters["target_id"] if "target_id" in huaweicloud_dew_block.dew_parameters else None, + target_name = huaweicloud_dew_block.dew_parameters["target_name"] if "target_name" in huaweicloud_dew_block.dew_parameters else None, + recovery_window_in_days = huaweicloud_dew_block.dew_parameters["recovery_window_in_days"] if "recovery_window_in_days" in huaweicloud_dew_block.dew_parameters else None, ) -@flow -def test_key_lifecycle_management(kms_params, huaweicloud_dew_block): - row_key_alias = kms_params['key_alias'] - huaweicloud_dew_block.create_key(**kms_params) - huaweicloud_dew_block.disable_key(**kms_params) - huaweicloud_dew_block.enable_key(**kms_params) + +@flow(name = "test_key_lifecycle_management") +def test_key_lifecycle_management(kms_params): + row_key_alias = kms_params.get('key_alias') + huaweicloud_dew_block.create_key(DewBlock.CreatekeyOptions(key_alias = kms_params.get('key_alias'))) + huaweicloud_dew_block.disable_key(key_id = kms_params.get('key_id')) + huaweicloud_dew_block.enable_key(key_id = kms_params.get('key_id')) kms_params['key_alias'] = "test_alias" - huaweicloud_dew_block.update_key_Alias(**kms_params) + huaweicloud_dew_block.update_key_alias(key_id = kms_params.get('key_id'), key_alias = kms_params.get('key_alias')) kms_params['key_alias'] = row_key_alias - huaweicloud_dew_block.update_key_Alias(**kms_params) + huaweicloud_dew_block.update_key_alias(key_id = kms_params.get('key_id'), key_alias = kms_params.get('key_alias')) kms_params['key_description'] = "test_update_description" - huaweicloud_dew_block.update_key_description(**kms_params) - huaweicloud_dew_block.delete_key(**kms_params) - huaweicloud_dew_block.cancel_key_deletion(**kms_params) - huaweicloud_dew_block.enable_key(**kms_params) + huaweicloud_dew_block.update_key_description(key_id = kms_params.get('key_id'), key_description = kms_params.get('key_description')) + huaweicloud_dew_block.delete_key(key_id = kms_params.get('key_id'), pending_days = kms_params.get('pending_days')) + huaweicloud_dew_block.cancel_key_deletion(key_id = kms_params.get('key_id')) + huaweicloud_dew_block.enable_key(key_id = kms_params.get('key_id')) -@flow -def test_data_key_management(kms_params, huaweicloud_dew_block): - huaweicloud_dew_block.create_data_key_without_plaintext(**kms_params) - create_data_key_response = huaweicloud_dew_block.create_data_key(**kms_params) - huaweicloud_dew_block.create_random(**kms_params) +@flow(name = 'test_data_key_management') +def test_data_key_management(kms_params): + huaweicloud_dew_block.create_data_key_without_plaintext(key_id = kms_params.get('key_id')) + create_data_key_response = huaweicloud_dew_block.create_data_key(key_id = kms_params.get('key_id'), datakey_length = kms_params.get('datakey_length')) + huaweicloud_dew_block.create_random(random_data_length = kms_params.get('random_data_length')) kms_params["cipher_text"] = create_data_key_response.cipher_text - decrypt_data_key_response = huaweicloud_dew_block.decrypt_data_key(**kms_params) + decrypt_data_key_response = huaweicloud_dew_block.decrypt_data_key(key_id = kms_params.get('key_id'), cipher_text = kms_params.get('cipher_text'), datakey_cipher_length = kms_params.get('datakey_cipher_length')) kms_params["datakey_dgst"] = decrypt_data_key_response.datakey_dgst kms_params["plain_text"] = decrypt_data_key_response.data_key+decrypt_data_key_response.datakey_dgst - huaweicloud_dew_block.encrypt_data_key(**kms_params) + huaweicloud_dew_block.encrypt_data_key(key_id = kms_params.get('key_id'), plain_text = kms_params.get('plain_text'), datakey_plain_length = kms_params.get('datakey_plain_length')) -@flow -def test_key_grant_management(kms_params, huaweicloud_dew_block): - create_grant_response = huaweicloud_dew_block.create_grant(**kms_params) +@flow(name = 'test_key_grant_management') +def test_key_grant_management(kms_params): + create_grant_response = huaweicloud_dew_block.create_grant(DewBlock.CreateGrantOptions(key_id = kms_params.get('key_id'), + grantee_principal = kms_params.get("grantee_principal"), listOperationsbody = kms_params.get("listOperationsbody"))) kms_params["grant_id"] = create_grant_response.grant_id - huaweicloud_dew_block.list_retirable_grants(**kms_params) - huaweicloud_dew_block.cancel_self_grant(**kms_params) - huaweicloud_dew_block.create_grant(**kms_params) - huaweicloud_dew_block.cancel_grant(**kms_params) - huaweicloud_dew_block.list_grants(**kms_params) - - -@flow -def test_key_pair_management(kps_params, huaweicloud_dew_block): - huaweicloud_dew_block.import_private_key(**kps_params) - huaweicloud_dew_block.export_private_key(**kps_params) - huaweicloud_dew_block.list_keypair_detail(**kps_params) - huaweicloud_dew_block.list_keypairs(**kps_params) - huaweicloud_dew_block.clear_private_key(**kps_params) + huaweicloud_dew_block.list_retirable_grants() + huaweicloud_dew_block.cancel_self_grant(key_id = kms_params.get('key_id'), grant_id = kms_params.get('grant_id')) + huaweicloud_dew_block.create_grant(DewBlock.CreateGrantOptions(key_id = kms_params.get('key_id'), + grantee_principal = kms_params.get("grantee_principal"), listOperationsbody = kms_params.get("listOperationsbody"))) + huaweicloud_dew_block.cancel_grant(key_id = kms_params.get('key_id'), grant_id = kms_params.get('grant_id')) + huaweicloud_dew_block.list_grants(key_id = kms_params.get('key_id')) + + +@flow(name = 'test_key_pair_management') +def test_key_pair_management(kps_params): + huaweicloud_dew_block.import_private_key(name = kps_params.get('name'), type = kps_params.get('type'), kms_key_name = kps_params.get('kms_key_name'), private_key = kps_params.get('private_key')) + huaweicloud_dew_block.export_private_key(name = kps_params.get('name')) + huaweicloud_dew_block.list_keypair_detail(keypair_name = kps_params.get('keypair_name')) + huaweicloud_dew_block.list_keypairs() + huaweicloud_dew_block.clear_private_key(keypair_name = kps_params.get('keypair_name')) kps_params['description'] = "test_update_description" - huaweicloud_dew_block.update_keypair_description(**kps_params) - - huaweicloud_dew_block.delete_keypair(**kps_params) - -@flow -def test_key_pair_task_management(kps_params, huaweicloud_dew_block): - kps_params["task_id"] = huaweicloud_dew_block.associate_keypair(**kps_params).task_id - huaweicloud_dew_block.batch_associate_keypair(**kps_params) - # huaweicloud_dew_block.delete_failed_task(**kps_params) - huaweicloud_dew_block.delete_all_failed_task(**kps_params) - huaweicloud_dew_block.disassociate_keypair(**kps_params) - huaweicloud_dew_block.list_failed_task(**kps_params) - huaweicloud_dew_block.list_keypair_task(**kps_params) - huaweicloud_dew_block.list_running_task(**kps_params) - -@flow -def test_small_data_encryption(kms_params, huaweicloud_dew_block): - encrypt_data_response = huaweicloud_dew_block.encrypt_data(**kms_params) - kms_params["cipher_text"] = encrypt_data_response.cipher_text - huaweicloud_dew_block.decrypt_data(**kms_params) - + huaweicloud_dew_block.update_keypair_description(keypair_name = kps_params.get('keypair_name'), description = kps_params.get('description')) + huaweicloud_dew_block.delete_keypair(keypair_name = kps_params.get('keypair_name')) -@flow -def test_list_key(kms_params, huaweicloud_dew_block): - huaweicloud_dew_block.list_keys(**kms_params) - huaweicloud_dew_block.list_key_detail(**kms_params) - huaweicloud_dew_block.show_public_key(**kms_params) - huaweicloud_dew_block.show_user_instances(**kms_params) - huaweicloud_dew_block.show_user_quotas(**kms_params) +@flow(name = 'test_key_pair_task_management') +def test_key_pair_task_management(kps_params): + kps_params["task_id"] = huaweicloud_dew_block.associate_keypair(DewBlock.AssociateKeypairOptions(keypair_name = kps_params.get('keypair_name'), + id = kps_params.get('id'), type = kps_params.get('type'), key = kps_params.get('key'), disable_password = kps_params.get('disable_password'))).task_id + huaweicloud_dew_block.batch_associate_keypair(DewBlock.BatchAssociateKeypairOptions(keypair_name = kps_params.get('keypair_name'), + id = kps_params.get('id'), type = kps_params.get('type'), key = kps_params.get('key'), disable_password = kps_params.get('disable_password'))) + huaweicloud_dew_block.delete_all_failed_task() + huaweicloud_dew_block.disassociate_keypair(id = kps_params.get('id'), type = kps_params.get('type'), key = kps_params.get('key')) + huaweicloud_dew_block.list_failed_task() + huaweicloud_dew_block.list_keypair_task(task_id = kps_params.get('task_id')) + huaweicloud_dew_block.list_running_task() -@flow -def test_key_rotation_management(kms_params, huaweicloud_dew_block): - huaweicloud_dew_block.enable_key_rotation(**kms_params) - huaweicloud_dew_block.show_key_rotation_status(**kms_params) - huaweicloud_dew_block.update_key_rotation_interval(**kms_params) - huaweicloud_dew_block.disable_key_rotation(**kms_params) - -@flow -def test_signature_verification(kms_params, huaweicloud_dew_block): - kms_params["key_id"] = "95afc13e-a5ed-4271-b8e9-a71079e8c6b3" - row_sign = huaweicloud_dew_block.sign(**kms_params) - kms_params['signature'] = row_sign.signature - huaweicloud_dew_block.validate_signature(**kms_params) +@flow(name = 'test_small_data_encryption') +def test_small_data_encryption(kms_params): + encrypt_data_response = huaweicloud_dew_block.encrypt_data(key_id = kms_params.get("key_id"), plain_text = kms_params.get("plain_text"), encryption_algorithm = kms_params.get("encryption_algorithm")) + kms_params["cipher_text"] = encrypt_data_response.cipher_text + huaweicloud_dew_block.decrypt_data(cipher_text = kms_params.get("cipher_text"), key_id = kms_params.get("key_id"), encryption_algorithm = kms_params.get("encryption_algorithm")) -@flow -def test_lifecycle_management(csms_params, huaweicloud_dew_block): - huaweicloud_dew_block.show_secret(**csms_params) - csms_params["secret_blob"] = huaweicloud_dew_block.download_secret_blob(**csms_params).secret_blob - huaweicloud_dew_block.update_secret(**csms_params) - huaweicloud_dew_block.delete_secret_for_schedule(**csms_params) - huaweicloud_dew_block.restore_secret(**csms_params) - huaweicloud_dew_block.delete_secret(**csms_params) - huaweicloud_dew_block.upload_secret_blob(**csms_params) +@flow(name = 'test_list_key') +def test_list_key(kms_params): + huaweicloud_dew_block.list_keys(DewBlock.ListKeysOptions()) + huaweicloud_dew_block.list_key_detail(key_id = kms_params.get("key_id")) + huaweicloud_dew_block.show_public_key(asymmetric_key_id = kms_params.get("asymmetric_key_id")) + huaweicloud_dew_block.show_user_instances() + huaweicloud_dew_block.show_user_quotas() -@flow -def test_credential_version_management(csms_params, huaweicloud_dew_block): - huaweicloud_dew_block.create_secret_version(**csms_params) - huaweicloud_dew_block.show_secret_version(**csms_params) - huaweicloud_dew_block.list_secret_versions(**csms_params) - huaweicloud_dew_block.update_version(**csms_params) +@flow(name = 'test_key_rotation_management') +def test_key_rotation_management(kms_params): + huaweicloud_dew_block.enable_key_rotation(key_id = kms_params.get("key_id")) + huaweicloud_dew_block.show_key_rotation_status(key_id = kms_params.get("key_id")) + huaweicloud_dew_block.update_key_rotation_interval(key_id = kms_params.get("key_id"), rotation_interval = kms_params.get("rotation_interval")) + huaweicloud_dew_block.disable_key_rotation(key_id = kms_params.get("key_id")) -@flow -def test_credential_version_status_management(csms_params, huaweicloud_dew_block): - show_secret_stage_response = huaweicloud_dew_block.show_secret_stage(**csms_params) +@flow(name = 'test_signature_verification') +def test_signature_verification(kms_params): + row_sign = huaweicloud_dew_block.sign(kms_params.get("asymmetric_key_id"), kms_params.get("message"), + kms_params.get("signing_algorithm"), kms_params.get("message_type")) + kms_params['signature'] = row_sign.signature + huaweicloud_dew_block.validate_signature(options = DewBlock.ValidateSignatureOptions(asymmetric_key_id = kms_params.get("asymmetric_key_id"), + signature = kms_params.get("signature"), message = kms_params.get("message"), signing_algorithm = kms_params.get("signing_algorithm"), message_type = kms_params.get("message_type"))) + + +@flow(name = 'test_lifecycle_management') +def test_lifecycle_management(csms_params): + huaweicloud_dew_block.show_secret(secret_name = csms_params.get("secret_name")) + csms_params["secret_blob"] = huaweicloud_dew_block.download_secret_blob(secret_name = csms_params.get("secret_name")).secret_blob + huaweicloud_dew_block.update_secret(DewBlock.UpdateSecretOptions(secret_name = csms_params.get("secret_name"), )) + huaweicloud_dew_block.delete_secret_for_schedule(secret_name = csms_params.get("secret_name"), + recovery_window_in_days = csms_params.get("recovery_window_in_days")) + huaweicloud_dew_block.restore_secret(secret_name = csms_params.get("secret_name")) + huaweicloud_dew_block.delete_secret(secret_name = csms_params.get("secret_name")) + huaweicloud_dew_block.upload_secret_blob(secret_blob = csms_params.get("secret_blob")) + + +@flow(name = 'test_credential_version_management') +def test_credential_version_management(csms_params): + huaweicloud_dew_block.create_secret_version(secret_name = csms_params.get("secret_name"), secret_string = csms_params.get("secret_string")) + huaweicloud_dew_block.show_secret_version(secret_name = csms_params.get("secret_name"), version_id = csms_params.get("version_id")) + huaweicloud_dew_block.list_secret_versions(secret_name = csms_params.get("secret_name")) + huaweicloud_dew_block.update_version(secret_name = csms_params.get("secret_name"), version_id = csms_params.get("version_id"), expire_time = csms_params.get("expire_time")) + + +@flow(name = 'test_credential_version_status_management') +def test_credential_version_status_management(csms_params): + show_secret_stage_response = huaweicloud_dew_block.show_secret_stage(secret_name = csms_params.get("secret_name"), + stage_name = csms_params.get("stage_name")) csms_params["stage_name"] = csms_params["update_stage_name"] csms_params["version_id"] = show_secret_stage_response.stage.version_id - huaweicloud_dew_block.update_secret_stage(**csms_params) - huaweicloud_dew_block.delete_secret_stage(**csms_params) - - -@flow -def test_voucher_label_management(csms_params, huaweicloud_dew_block): - huaweicloud_dew_block.batch_create_or_delete_tags(**csms_params) - huaweicloud_dew_block.create_secret_tag(**csms_params) - huaweicloud_dew_block.list_project_secrets_tags(**csms_params) - huaweicloud_dew_block.list_resource_instances(csms_params["resource_instances"],action=csms_params["action1"]) - huaweicloud_dew_block.list_secret_tags(**csms_params) - huaweicloud_dew_block.delete_secret_tag(**csms_params) - - -@flow -def test_event_management(csms_params, huaweicloud_dew_block): - huaweicloud_dew_block.create_secret_event(**csms_params) - huaweicloud_dew_block.show_secret_event(**csms_params) - huaweicloud_dew_block.update_secret_event(**csms_params) - huaweicloud_dew_block.delete_secret_event(**csms_params) - huaweicloud_dew_block.list_notification_records(**csms_params) - - -@flow -def test_key_label_management(kms_params, huaweicloud_dew_block): - huaweicloud_dew_block.list_kms_tags(**kms_params) - huaweicloud_dew_block.batch_create_kms_tags(**kms_params) - huaweicloud_dew_block.create_kms_tag(**kms_params) - huaweicloud_dew_block.list_kms_by_tags(action = "count") - huaweicloud_dew_block.show_kms_tags(**kms_params) - huaweicloud_dew_block.delete_tag(**kms_params) - -@flow -def test_query_key_api_version_information(kms_params, huaweicloud_dew_block): - huaweicloud_dew_block.show_versions(**kms_params) - huaweicloud_dew_block.show_version(**kms_params) + huaweicloud_dew_block.update_secret_stage(secret_name = csms_params.get("secret_name"), + stage_name = csms_params.get("stage_name"), + version_id = csms_params.get("version_id")) + huaweicloud_dew_block.delete_secret_stage(secret_name = csms_params.get("secret_name"), + stage_name = csms_params.get("stage_name")) + + +@flow(name = 'test_voucher_label_management') +def test_voucher_label_management(csms_params): + huaweicloud_dew_block.batch_create_or_delete_tags(secret_id = csms_params.get("secret_id"), + key = csms_params.get("key"), action = csms_params.get("action")) + huaweicloud_dew_block.create_secret_tag(secret_id = csms_params.get("secret_id"), key = csms_params.get("key")) + huaweicloud_dew_block.list_project_secrets_tags() + huaweicloud_dew_block.list_resource_instances(DewBlock.ListResourceInstancesOptions( + action = csms_params.get("action1"), resource_instances = csms_params.get("resource_instances"))) + huaweicloud_dew_block.list_secret_tags(secret_id = csms_params.get("secret_id")) + huaweicloud_dew_block.delete_secret_tag(secret_id = csms_params.get("secret_id"), key = csms_params.get("key")) + + +@flow(name = 'test_event_management') +def test_event_management(csms_params): + huaweicloud_dew_block.create_secret_event(DewBlock.CreateSecretEventOptions(target_type = csms_params.get("target_type"), + target_id = csms_params.get("target_id"), + target_name = csms_params.get("target_name"), + event_name = csms_params.get("event_name"), + event_types = csms_params.get("event_types"), + state = csms_params.get("state"))) + huaweicloud_dew_block.show_secret_event(event_name = csms_params.get("event_name")) + huaweicloud_dew_block.update_secret_event(event_name = csms_params.get("event_name"), + target_type = csms_params.get("target_type"), + target_id = csms_params.get("target_id"), + target_name = csms_params.get("target_name")) + huaweicloud_dew_block.delete_secret_event(event_name = csms_params.get("event_name")) + huaweicloud_dew_block.list_notification_records() + + +@flow(name = 'test_key_label_management') +def test_key_label_management(kms_params): + huaweicloud_dew_block.list_kms_tags() + huaweicloud_dew_block.batch_create_kms_tags(key_id = kms_params.get("key_id"), key = [kms_params.get("key")], action = kms_params.get("action")) + huaweicloud_dew_block.create_kms_tag(key_id = kms_params.get("key_id"), key = kms_params.get("key")) + huaweicloud_dew_block.list_kms_by_tags(DewBlock.ListKmsByTagsOptions(action = "count")) + huaweicloud_dew_block.show_kms_tags(key_id = kms_params.get("key_id")) + huaweicloud_dew_block.delete_tag(key_id = kms_params.get("key_id"), key = kms_params.get("key")) + +@flow(name = 'test_query_key_api_version_information') +def test_query_key_api_version_information(kms_params): + huaweicloud_dew_block.show_versions() + huaweicloud_dew_block.show_version(version_id = kms_params.get("version_id")) if __name__ == "__main__": - huaweicloud_dew_block = DewBlock.load("test-dew-block") - # test_key_lifecycle_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_data_key_management(kms_params, huaweicloud_dew_block) - # test_small_data_encryption(kms_params, huaweicloud_dew_block) - # test_list_key(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_query_key_api_version_information(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_key_grant_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_signature_verification(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_key_label_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_key_rotation_management(kms_params(huaweicloud_dew_block), huaweicloud_dew_block) - - - # test_key_pair_task_management(kps_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_key_pair_management(kps_params(huaweicloud_dew_block), huaweicloud_dew_block) - - # csms_params = csms_params(huaweicloud_dew_block, name = "demo", secret_string = "test_secret", secret_type = None, event_name = "demo_event") - # test_credential_version_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_lifecycle_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_credential_version_status_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_voucher_label_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) - # test_event_management(csms_params(huaweicloud_dew_block), huaweicloud_dew_block) + huaweicloud_dew_block = DewBlock.load("test-dew-block") + test_event_management(csms_parameters()) + + + # test_key_lifecycle_management(kms_parameters()) + # test_key_grant_management(kms_parameters()) + # test_signature_verification(kms_parameters()) + # test_key_label_management(kms_parameters()) + # test_key_rotation_management(kms_parameters()) + # temp_kms_parameters = kms_parameters() + # test_data_key_management(temp_kms_parameters) + # test_small_data_encryption(temp_kms_parameters) + # test_key_grant_management(kms_parameters()) + # test_query_key_api_version_information(kms_parameters()) + # test_list_key(kms_parameters()) + + # test_key_pair_task_management(kps_parameters()) + # test_key_pair_management(kps_parameters()) + + # test_lifecycle_management(csms_parameters()) + # test_credential_version_status_management(csms_parameters()) + # test_credential_version_management(csms_parameters()) + # test_voucher_label_management(csms_parameters()) -- Gitee From c6854fd348782437a5df913ae2aaf3047844e508 Mon Sep 17 00:00:00 2001 From: Lky0312 <523175094@qq.com> Date: Thu, 14 Mar 2024 11:53:40 +0800 Subject: [PATCH 09/11] =?UTF-8?q?=E6=94=B9=E8=BF=9B=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E4=B9=A6=E5=86=99=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefect_huaweicloud/dew_block.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/prefect_huaweicloud/dew_block.py b/prefect_huaweicloud/dew_block.py index 8201574..2a5fe9c 100644 --- a/prefect_huaweicloud/dew_block.py +++ b/prefect_huaweicloud/dew_block.py @@ -61,7 +61,7 @@ class DewBlock(Block): def __init__(self,name=None,kms_key_id=None,description=None,secret_binary=None,secret_string=None, secret_type=None,auto_rotation=None,rotation_period=None,rotation_config=None, event_subscriptions=None,enterprise_project_id=None): - self.name = Name + self.name = name self.kms_key_id = kms_key_id self.description = description self.secret_binary = secret_binary @@ -111,7 +111,7 @@ class DewBlock(Block): self.key_id = key_id self.grantee_principal = grantee_principal self.listOperationsbody = listOperationsbody - self.name = Name + self.name = name self.grantee_principal_type = grantee_principal_type self.retiring_principal = retiring_principal self.sequence = sequence @@ -149,7 +149,7 @@ class DewBlock(Block): @dataclass class CreateKeypairOptions: def __init__(self, name=None, type=None, public_key=None, scope=None, user_id=None, key_protection=None): - self.name = Name + self.name = name self.type = type self.public_key = public_key self.scope = scope @@ -1283,7 +1283,7 @@ class DewBlock(Block): encryption=encryption_key_protection ) key_pair_body = ImportPrivateKeyKeypairBean( - name = Name, + name = name, key_protection=key_protection_keypair, user_id=user_id ) @@ -1355,7 +1355,7 @@ class DewBlock(Block): """ try: request = ExportPrivateKeyRequest() - key_pair_body = KeypairBean(name = Name) + key_pair_body = KeypairBean(name = name) request.body = ExportPrivateKeyRequestBody(keypair=key_pair_body) response = self._dew_client.kps_client.export_private_key(request) self.logger.info("Successfully exported private key:") -- Gitee From 2470778916241736f7f1822271f26b66d11fb37d Mon Sep 17 00:00:00 2001 From: Lky0312 <523175094@qq.com> Date: Sat, 16 Mar 2024 11:11:59 +0800 Subject: [PATCH 10/11] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E7=9A=84=E4=BB=A3=E7=A0=81=E4=B9=A6=E5=86=99?= =?UTF-8?q?=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefect_huaweicloud/test/test_dew_block.py | 189 ++++++++++----------- 1 file changed, 88 insertions(+), 101 deletions(-) diff --git a/prefect_huaweicloud/test/test_dew_block.py b/prefect_huaweicloud/test/test_dew_block.py index 2c218a9..1d33d12 100644 --- a/prefect_huaweicloud/test/test_dew_block.py +++ b/prefect_huaweicloud/test/test_dew_block.py @@ -3,6 +3,19 @@ from pathlib import Path sys.path.append(str(Path(__file__).resolve().parents[1])) from dew_block import DewBlock from prefect import flow + +KEY_ID='key_id' +KEY_ALIAS='key_alias' +GRANT_ID='grant_id' +KEYPAIR_NAME='keypair_name' +KEY='key' +TYPE='type' +ID='id' +SECRET_NAME='secret_name' +SECRET_ID='secret_id' +STAGE_NAME='stage_name' +STAGE_ID='stage_id' +EVENT_NAME='event_name' def kms_parameters(): test_key = None key_alias = None @@ -37,7 +50,7 @@ def kms_parameters(): signature = None, action = huaweicloud_dew_block.dew_parameters["action"] if "action" in huaweicloud_dew_block.dew_parameters else None, - key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, + key = huaweicloud_dew_block.dew_parameters[KEY] if KEY in huaweicloud_dew_block.dew_parameters else None, version_id = huaweicloud_dew_block.dew_parameters["version_id"] if "version_id" in huaweicloud_dew_block.dew_parameters else None, ) @@ -59,7 +72,7 @@ def kps_parameters(): id = huaweicloud_dew_block.dew_parameters["id"] if "id" in huaweicloud_dew_block.dew_parameters else None, kms_key_name = huaweicloud_dew_block.dew_parameters["kms_key_name"] if "kms_key_name" in huaweicloud_dew_block.dew_parameters else None, type = huaweicloud_dew_block.dew_parameters["type"] if "type" in huaweicloud_dew_block.dew_parameters else None, - key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, + key = huaweicloud_dew_block.dew_parameters[KEY] if KEY in huaweicloud_dew_block.dew_parameters else None, task_id = None, disable_password = huaweicloud_dew_block.dew_parameters["disable_password"] if "disable_password" in huaweicloud_dew_block.dew_parameters else None, ) @@ -88,18 +101,18 @@ def csms_parameters(): secret_blob = None, expire_time = huaweicloud_dew_block.dew_parameters["expire_time"] if "expire_time" in huaweicloud_dew_block.dew_parameters else None, secret_string = secret_string, - stage_name = huaweicloud_dew_block.dew_parameters["stage_name"] if "stage_name" in huaweicloud_dew_block.dew_parameters else None, + stage_name = huaweicloud_dew_block.dew_parameters[STAGE_NAME] if STAGE_NAME in huaweicloud_dew_block.dew_parameters else None, update_stage_name = huaweicloud_dew_block.dew_parameters["update_stage_name"] if "update_stage_name" in huaweicloud_dew_block.dew_parameters else None, update_version_id = huaweicloud_dew_block.dew_parameters["update_version_id"] if "update_version_id" in huaweicloud_dew_block.dew_parameters else None, secret_id = test_secret.secret.id, - key = huaweicloud_dew_block.dew_parameters["key"] if "key" in huaweicloud_dew_block.dew_parameters else None, + key = huaweicloud_dew_block.dew_parameters[KEY] if KEY in huaweicloud_dew_block.dew_parameters else None, action = huaweicloud_dew_block.dew_parameters["action0"] if "action0" in huaweicloud_dew_block.dew_parameters else None, action1 = huaweicloud_dew_block.dew_parameters["action1"] if "action1" in huaweicloud_dew_block.dew_parameters else None, value = huaweicloud_dew_block.dew_parameters["value"] if "value" in huaweicloud_dew_block.dew_parameters else None, values = huaweicloud_dew_block.dew_parameters["values"] if "values" in huaweicloud_dew_block.dew_parameters else None, resource_instances = huaweicloud_dew_block.dew_parameters["resource_instances"] if "resource_instances" in huaweicloud_dew_block.dew_parameters else None, - event_name = huaweicloud_dew_block.dew_parameters["event_name"] if "event_name" in huaweicloud_dew_block.dew_parameters else None, + event_name = huaweicloud_dew_block.dew_parameters[EVENT_NAME] if EVENT_NAME in huaweicloud_dew_block.dew_parameters else None, event_types = huaweicloud_dew_block.dew_parameters["event_types"] if "event_types" in huaweicloud_dew_block.dew_parameters else None, state = huaweicloud_dew_block.dew_parameters["state"] if "state" in huaweicloud_dew_block.dew_parameters else None, target_type = huaweicloud_dew_block.dew_parameters["target_type"] if "target_type" in huaweicloud_dew_block.dew_parameters else None, @@ -112,68 +125,68 @@ def csms_parameters(): @flow(name = "test_key_lifecycle_management") def test_key_lifecycle_management(kms_params): - row_key_alias = kms_params.get('key_alias') - huaweicloud_dew_block.create_key(DewBlock.CreatekeyOptions(key_alias = kms_params.get('key_alias'))) - huaweicloud_dew_block.disable_key(key_id = kms_params.get('key_id')) - huaweicloud_dew_block.enable_key(key_id = kms_params.get('key_id')) - kms_params['key_alias'] = "test_alias" - huaweicloud_dew_block.update_key_alias(key_id = kms_params.get('key_id'), key_alias = kms_params.get('key_alias')) - kms_params['key_alias'] = row_key_alias - huaweicloud_dew_block.update_key_alias(key_id = kms_params.get('key_id'), key_alias = kms_params.get('key_alias')) + row_key_alias = kms_params.get(KEY_ALIAS) + huaweicloud_dew_block.create_key(DewBlock.CreatekeyOptions(key_alias = kms_params.get(KEY_ALIAS))) + huaweicloud_dew_block.disable_key(key_id = kms_params.get(KEY_ID)) + huaweicloud_dew_block.enable_key(key_id = kms_params.get(KEY_ID)) + kms_params[KEY_ALIAS] = "test_alias" + huaweicloud_dew_block.update_key_alias(key_id = kms_params.get(KEY_ID), key_alias = kms_params.get(KEY_ALIAS)) + kms_params[KEY_ALIAS] = row_key_alias + huaweicloud_dew_block.update_key_alias(key_id = kms_params.get(KEY_ID), key_alias = kms_params.get(KEY_ALIAS)) kms_params['key_description'] = "test_update_description" - huaweicloud_dew_block.update_key_description(key_id = kms_params.get('key_id'), key_description = kms_params.get('key_description')) - huaweicloud_dew_block.delete_key(key_id = kms_params.get('key_id'), pending_days = kms_params.get('pending_days')) - huaweicloud_dew_block.cancel_key_deletion(key_id = kms_params.get('key_id')) - huaweicloud_dew_block.enable_key(key_id = kms_params.get('key_id')) + huaweicloud_dew_block.update_key_description(key_id = kms_params.get(KEY_ID), key_description = kms_params.get('key_description')) + huaweicloud_dew_block.delete_key(key_id = kms_params.get(KEY_ID), pending_days = kms_params.get('pending_days')) + huaweicloud_dew_block.cancel_key_deletion(key_id = kms_params.get(KEY_ID)) + huaweicloud_dew_block.enable_key(key_id = kms_params.get(KEY_ID)) @flow(name = 'test_data_key_management') def test_data_key_management(kms_params): - huaweicloud_dew_block.create_data_key_without_plaintext(key_id = kms_params.get('key_id')) - create_data_key_response = huaweicloud_dew_block.create_data_key(key_id = kms_params.get('key_id'), datakey_length = kms_params.get('datakey_length')) + huaweicloud_dew_block.create_data_key_without_plaintext(key_id = kms_params.get(KEY_ID)) + create_data_key_response = huaweicloud_dew_block.create_data_key(key_id = kms_params.get(KEY_ID), datakey_length = kms_params.get('datakey_length')) huaweicloud_dew_block.create_random(random_data_length = kms_params.get('random_data_length')) kms_params["cipher_text"] = create_data_key_response.cipher_text - decrypt_data_key_response = huaweicloud_dew_block.decrypt_data_key(key_id = kms_params.get('key_id'), cipher_text = kms_params.get('cipher_text'), datakey_cipher_length = kms_params.get('datakey_cipher_length')) + decrypt_data_key_response = huaweicloud_dew_block.decrypt_data_key(key_id = kms_params.get(KEY_ID), cipher_text = kms_params.get('cipher_text'), datakey_cipher_length = kms_params.get('datakey_cipher_length')) kms_params["datakey_dgst"] = decrypt_data_key_response.datakey_dgst kms_params["plain_text"] = decrypt_data_key_response.data_key+decrypt_data_key_response.datakey_dgst - huaweicloud_dew_block.encrypt_data_key(key_id = kms_params.get('key_id'), plain_text = kms_params.get('plain_text'), datakey_plain_length = kms_params.get('datakey_plain_length')) + huaweicloud_dew_block.encrypt_data_key(key_id = kms_params.get(KEY_ID), plain_text = kms_params.get('plain_text'), datakey_plain_length = kms_params.get('datakey_plain_length')) @flow(name = 'test_key_grant_management') def test_key_grant_management(kms_params): - create_grant_response = huaweicloud_dew_block.create_grant(DewBlock.CreateGrantOptions(key_id = kms_params.get('key_id'), + create_grant_response = huaweicloud_dew_block.create_grant(DewBlock.CreateGrantOptions(key_id = kms_params.get(KEY_ID), grantee_principal = kms_params.get("grantee_principal"), listOperationsbody = kms_params.get("listOperationsbody"))) - kms_params["grant_id"] = create_grant_response.grant_id + kms_params[GRANT_ID] = create_grant_response.grant_id huaweicloud_dew_block.list_retirable_grants() - huaweicloud_dew_block.cancel_self_grant(key_id = kms_params.get('key_id'), grant_id = kms_params.get('grant_id')) - huaweicloud_dew_block.create_grant(DewBlock.CreateGrantOptions(key_id = kms_params.get('key_id'), + huaweicloud_dew_block.cancel_self_grant(key_id = kms_params.get(KEY_ID), grant_id = kms_params.get(GRANT_ID)) + huaweicloud_dew_block.create_grant(DewBlock.CreateGrantOptions(key_id = kms_params.get(KEY_ID), grantee_principal = kms_params.get("grantee_principal"), listOperationsbody = kms_params.get("listOperationsbody"))) - huaweicloud_dew_block.cancel_grant(key_id = kms_params.get('key_id'), grant_id = kms_params.get('grant_id')) - huaweicloud_dew_block.list_grants(key_id = kms_params.get('key_id')) + huaweicloud_dew_block.cancel_grant(key_id = kms_params.get(KEY_ID), grant_id = kms_params.get(GRANT_ID)) + huaweicloud_dew_block.list_grants(key_id = kms_params.get(KEY_ID)) @flow(name = 'test_key_pair_management') def test_key_pair_management(kps_params): - huaweicloud_dew_block.import_private_key(name = kps_params.get('name'), type = kps_params.get('type'), kms_key_name = kps_params.get('kms_key_name'), private_key = kps_params.get('private_key')) + huaweicloud_dew_block.import_private_key(name = kps_params.get('name'), type = kps_params.get(TYPE), kms_key_name = kps_params.get('kms_key_name'), private_key = kps_params.get('private_key')) huaweicloud_dew_block.export_private_key(name = kps_params.get('name')) - huaweicloud_dew_block.list_keypair_detail(keypair_name = kps_params.get('keypair_name')) + huaweicloud_dew_block.list_keypair_detail(keypair_name = kps_params.get(KEYPAIR_NAME)) huaweicloud_dew_block.list_keypairs() - huaweicloud_dew_block.clear_private_key(keypair_name = kps_params.get('keypair_name')) + huaweicloud_dew_block.clear_private_key(keypair_name = kps_params.get(KEYPAIR_NAME)) kps_params['description'] = "test_update_description" - huaweicloud_dew_block.update_keypair_description(keypair_name = kps_params.get('keypair_name'), description = kps_params.get('description')) + huaweicloud_dew_block.update_keypair_description(keypair_name = kps_params.get(KEYPAIR_NAME), description = kps_params.get('description')) - huaweicloud_dew_block.delete_keypair(keypair_name = kps_params.get('keypair_name')) + huaweicloud_dew_block.delete_keypair(keypair_name = kps_params.get(KEYPAIR_NAME)) @flow(name = 'test_key_pair_task_management') def test_key_pair_task_management(kps_params): - kps_params["task_id"] = huaweicloud_dew_block.associate_keypair(DewBlock.AssociateKeypairOptions(keypair_name = kps_params.get('keypair_name'), - id = kps_params.get('id'), type = kps_params.get('type'), key = kps_params.get('key'), disable_password = kps_params.get('disable_password'))).task_id - huaweicloud_dew_block.batch_associate_keypair(DewBlock.BatchAssociateKeypairOptions(keypair_name = kps_params.get('keypair_name'), - id = kps_params.get('id'), type = kps_params.get('type'), key = kps_params.get('key'), disable_password = kps_params.get('disable_password'))) + kps_params["task_id"] = huaweicloud_dew_block.associate_keypair(DewBlock.AssociateKeypairOptions(keypair_name = kps_params.get(KEYPAIR_NAME), + id = kps_params.get(ID), type = kps_params.get(TYPE), key = kps_params.get(KEY), disable_password = kps_params.get('disable_password'))).task_id + huaweicloud_dew_block.batch_associate_keypair(DewBlock.BatchAssociateKeypairOptions(keypair_name = kps_params.get(KEYPAIR_NAME), + id = kps_params.get(ID), type = kps_params.get(TYPE), key = kps_params.get(KEY), disable_password = kps_params.get('disable_password'))) huaweicloud_dew_block.delete_all_failed_task() - huaweicloud_dew_block.disassociate_keypair(id = kps_params.get('id'), type = kps_params.get('type'), key = kps_params.get('key')) + huaweicloud_dew_block.disassociate_keypair(id = kps_params.get(ID), type = kps_params.get(TYPE), key = kps_params.get(KEY)) huaweicloud_dew_block.list_failed_task() huaweicloud_dew_block.list_keypair_task(task_id = kps_params.get('task_id')) huaweicloud_dew_block.list_running_task() @@ -181,15 +194,15 @@ def test_key_pair_task_management(kps_params): @flow(name = 'test_small_data_encryption') def test_small_data_encryption(kms_params): - encrypt_data_response = huaweicloud_dew_block.encrypt_data(key_id = kms_params.get("key_id"), plain_text = kms_params.get("plain_text"), encryption_algorithm = kms_params.get("encryption_algorithm")) + encrypt_data_response = huaweicloud_dew_block.encrypt_data(key_id = kms_params.get(KEY_ID), plain_text = kms_params.get("plain_text"), encryption_algorithm = kms_params.get("encryption_algorithm")) kms_params["cipher_text"] = encrypt_data_response.cipher_text - huaweicloud_dew_block.decrypt_data(cipher_text = kms_params.get("cipher_text"), key_id = kms_params.get("key_id"), encryption_algorithm = kms_params.get("encryption_algorithm")) + huaweicloud_dew_block.decrypt_data(cipher_text = kms_params.get("cipher_text"), key_id = kms_params.get(KEY_ID), encryption_algorithm = kms_params.get("encryption_algorithm")) @flow(name = 'test_list_key') def test_list_key(kms_params): huaweicloud_dew_block.list_keys(DewBlock.ListKeysOptions()) - huaweicloud_dew_block.list_key_detail(key_id = kms_params.get("key_id")) + huaweicloud_dew_block.list_key_detail(key_id = kms_params.get(KEY_ID)) huaweicloud_dew_block.show_public_key(asymmetric_key_id = kms_params.get("asymmetric_key_id")) huaweicloud_dew_block.show_user_instances() huaweicloud_dew_block.show_user_quotas() @@ -197,10 +210,10 @@ def test_list_key(kms_params): @flow(name = 'test_key_rotation_management') def test_key_rotation_management(kms_params): - huaweicloud_dew_block.enable_key_rotation(key_id = kms_params.get("key_id")) - huaweicloud_dew_block.show_key_rotation_status(key_id = kms_params.get("key_id")) - huaweicloud_dew_block.update_key_rotation_interval(key_id = kms_params.get("key_id"), rotation_interval = kms_params.get("rotation_interval")) - huaweicloud_dew_block.disable_key_rotation(key_id = kms_params.get("key_id")) + huaweicloud_dew_block.enable_key_rotation(key_id = kms_params.get(KEY_ID)) + huaweicloud_dew_block.show_key_rotation_status(key_id = kms_params.get(KEY_ID)) + huaweicloud_dew_block.update_key_rotation_interval(key_id = kms_params.get(KEY_ID), rotation_interval = kms_params.get("rotation_interval")) + huaweicloud_dew_block.disable_key_rotation(key_id = kms_params.get(KEY_ID)) @flow(name = 'test_signature_verification') @@ -214,47 +227,47 @@ def test_signature_verification(kms_params): @flow(name = 'test_lifecycle_management') def test_lifecycle_management(csms_params): - huaweicloud_dew_block.show_secret(secret_name = csms_params.get("secret_name")) - csms_params["secret_blob"] = huaweicloud_dew_block.download_secret_blob(secret_name = csms_params.get("secret_name")).secret_blob - huaweicloud_dew_block.update_secret(DewBlock.UpdateSecretOptions(secret_name = csms_params.get("secret_name"), )) - huaweicloud_dew_block.delete_secret_for_schedule(secret_name = csms_params.get("secret_name"), + huaweicloud_dew_block.show_secret(secret_name = csms_params.get(SECRET_NAME)) + csms_params["secret_blob"] = huaweicloud_dew_block.download_secret_blob(secret_name = csms_params.get(SECRET_NAME)).secret_blob + huaweicloud_dew_block.update_secret(DewBlock.UpdateSecretOptions(secret_name = csms_params.get(SECRET_NAME), )) + huaweicloud_dew_block.delete_secret_for_schedule(secret_name = csms_params.get(SECRET_NAME), recovery_window_in_days = csms_params.get("recovery_window_in_days")) - huaweicloud_dew_block.restore_secret(secret_name = csms_params.get("secret_name")) - huaweicloud_dew_block.delete_secret(secret_name = csms_params.get("secret_name")) + huaweicloud_dew_block.restore_secret(secret_name = csms_params.get(SECRET_NAME)) + huaweicloud_dew_block.delete_secret(secret_name = csms_params.get(SECRET_NAME)) huaweicloud_dew_block.upload_secret_blob(secret_blob = csms_params.get("secret_blob")) @flow(name = 'test_credential_version_management') def test_credential_version_management(csms_params): - huaweicloud_dew_block.create_secret_version(secret_name = csms_params.get("secret_name"), secret_string = csms_params.get("secret_string")) - huaweicloud_dew_block.show_secret_version(secret_name = csms_params.get("secret_name"), version_id = csms_params.get("version_id")) - huaweicloud_dew_block.list_secret_versions(secret_name = csms_params.get("secret_name")) - huaweicloud_dew_block.update_version(secret_name = csms_params.get("secret_name"), version_id = csms_params.get("version_id"), expire_time = csms_params.get("expire_time")) + huaweicloud_dew_block.create_secret_version(secret_name = csms_params.get(SECRET_NAME), secret_string = csms_params.get("secret_string")) + huaweicloud_dew_block.show_secret_version(secret_name = csms_params.get(SECRET_NAME), version_id = csms_params.get("version_id")) + huaweicloud_dew_block.list_secret_versions(secret_name = csms_params.get(SECRET_NAME)) + huaweicloud_dew_block.update_version(secret_name = csms_params.get(SECRET_NAME), version_id = csms_params.get("version_id"), expire_time = csms_params.get("expire_time")) @flow(name = 'test_credential_version_status_management') def test_credential_version_status_management(csms_params): - show_secret_stage_response = huaweicloud_dew_block.show_secret_stage(secret_name = csms_params.get("secret_name"), - stage_name = csms_params.get("stage_name")) - csms_params["stage_name"] = csms_params["update_stage_name"] + show_secret_stage_response = huaweicloud_dew_block.show_secret_stage(secret_name = csms_params.get(SECRET_NAME), + stage_name = csms_params.get(STAGE_NAME)) + csms_params[STAGE_NAME] = csms_params["update_stage_name"] csms_params["version_id"] = show_secret_stage_response.stage.version_id - huaweicloud_dew_block.update_secret_stage(secret_name = csms_params.get("secret_name"), - stage_name = csms_params.get("stage_name"), + huaweicloud_dew_block.update_secret_stage(secret_name = csms_params.get(SECRET_NAME), + stage_name = csms_params.get(STAGE_NAME), version_id = csms_params.get("version_id")) - huaweicloud_dew_block.delete_secret_stage(secret_name = csms_params.get("secret_name"), - stage_name = csms_params.get("stage_name")) + huaweicloud_dew_block.delete_secret_stage(secret_name = csms_params.get(SECRET_NAME), + stage_name = csms_params.get(STAGE_NAME)) @flow(name = 'test_voucher_label_management') def test_voucher_label_management(csms_params): - huaweicloud_dew_block.batch_create_or_delete_tags(secret_id = csms_params.get("secret_id"), - key = csms_params.get("key"), action = csms_params.get("action")) - huaweicloud_dew_block.create_secret_tag(secret_id = csms_params.get("secret_id"), key = csms_params.get("key")) + huaweicloud_dew_block.batch_create_or_delete_tags(secret_id = csms_params.getSECRET_ID, + key = csms_params.get(KEY), action = csms_params.get("action")) + huaweicloud_dew_block.create_secret_tag(secret_id = csms_params.getSECRET_ID, key = csms_params.get(KEY)) huaweicloud_dew_block.list_project_secrets_tags() huaweicloud_dew_block.list_resource_instances(DewBlock.ListResourceInstancesOptions( action = csms_params.get("action1"), resource_instances = csms_params.get("resource_instances"))) - huaweicloud_dew_block.list_secret_tags(secret_id = csms_params.get("secret_id")) - huaweicloud_dew_block.delete_secret_tag(secret_id = csms_params.get("secret_id"), key = csms_params.get("key")) + huaweicloud_dew_block.list_secret_tags(secret_id = csms_params.getSECRET_ID) + huaweicloud_dew_block.delete_secret_tag(secret_id = csms_params.getSECRET_ID, key = csms_params.get(KEY)) @flow(name = 'test_event_management') @@ -262,26 +275,26 @@ def test_event_management(csms_params): huaweicloud_dew_block.create_secret_event(DewBlock.CreateSecretEventOptions(target_type = csms_params.get("target_type"), target_id = csms_params.get("target_id"), target_name = csms_params.get("target_name"), - event_name = csms_params.get("event_name"), + event_name = csms_params.get(EVENT_NAME), event_types = csms_params.get("event_types"), state = csms_params.get("state"))) - huaweicloud_dew_block.show_secret_event(event_name = csms_params.get("event_name")) - huaweicloud_dew_block.update_secret_event(event_name = csms_params.get("event_name"), + huaweicloud_dew_block.show_secret_event(event_name = csms_params.get(EVENT_NAME)) + huaweicloud_dew_block.update_secret_event(event_name = csms_params.get(EVENT_NAME), target_type = csms_params.get("target_type"), target_id = csms_params.get("target_id"), target_name = csms_params.get("target_name")) - huaweicloud_dew_block.delete_secret_event(event_name = csms_params.get("event_name")) + huaweicloud_dew_block.delete_secret_event(event_name = csms_params.get(EVENT_NAME)) huaweicloud_dew_block.list_notification_records() @flow(name = 'test_key_label_management') def test_key_label_management(kms_params): huaweicloud_dew_block.list_kms_tags() - huaweicloud_dew_block.batch_create_kms_tags(key_id = kms_params.get("key_id"), key = [kms_params.get("key")], action = kms_params.get("action")) - huaweicloud_dew_block.create_kms_tag(key_id = kms_params.get("key_id"), key = kms_params.get("key")) + huaweicloud_dew_block.batch_create_kms_tags(key_id = kms_params.get(KEY_ID), key = [kms_params.get(KEY)], action = kms_params.get("action")) + huaweicloud_dew_block.create_kms_tag(key_id = kms_params.get(KEY_ID), key = kms_params.get(KEY)) huaweicloud_dew_block.list_kms_by_tags(DewBlock.ListKmsByTagsOptions(action = "count")) - huaweicloud_dew_block.show_kms_tags(key_id = kms_params.get("key_id")) - huaweicloud_dew_block.delete_tag(key_id = kms_params.get("key_id"), key = kms_params.get("key")) + huaweicloud_dew_block.show_kms_tags(key_id = kms_params.get(KEY_ID)) + huaweicloud_dew_block.delete_tag(key_id = kms_params.get(KEY_ID), key = kms_params.get(KEY)) @flow(name = 'test_query_key_api_version_information') def test_query_key_api_version_information(kms_params): @@ -291,30 +304,4 @@ def test_query_key_api_version_information(kms_params): if __name__ == "__main__": - huaweicloud_dew_block = DewBlock.load("test-dew-block") - test_event_management(csms_parameters()) - - - # test_key_lifecycle_management(kms_parameters()) - # test_key_grant_management(kms_parameters()) - # test_signature_verification(kms_parameters()) - # test_key_label_management(kms_parameters()) - # test_key_rotation_management(kms_parameters()) - # temp_kms_parameters = kms_parameters() - # test_data_key_management(temp_kms_parameters) - # test_small_data_encryption(temp_kms_parameters) - # test_key_grant_management(kms_parameters()) - # test_query_key_api_version_information(kms_parameters()) - # test_list_key(kms_parameters()) - - # test_key_pair_task_management(kps_parameters()) - # test_key_pair_management(kps_parameters()) - - # test_lifecycle_management(csms_parameters()) - # test_credential_version_status_management(csms_parameters()) - # test_credential_version_management(csms_parameters()) - # test_voucher_label_management(csms_parameters()) - - - - + huaweicloud_dew_block = DewBlock.load("test-dew-block") \ No newline at end of file -- Gitee From 73bacab70ba9b10391e63f2358abb4e7db1bfcbc Mon Sep 17 00:00:00 2001 From: Lky0312 <523175094@qq.com> Date: Sun, 17 Mar 2024 11:11:12 +0800 Subject: [PATCH 11/11] final --- prefect_huaweicloud/dew_block.py | 846 +++++++++++++++---------------- 1 file changed, 415 insertions(+), 431 deletions(-) diff --git a/prefect_huaweicloud/dew_block.py b/prefect_huaweicloud/dew_block.py index 2a5fe9c..c4e5e2d 100644 --- a/prefect_huaweicloud/dew_block.py +++ b/prefect_huaweicloud/dew_block.py @@ -26,41 +26,41 @@ class DewBlock(Block): _documentation_url = ("https://support.huaweicloud.com/intl/zh-cn/sdkreference-dew/dew_02_0001.html") # noqa huawei_cloud_access_key_id: Optional[SecretStr] = Field( - default=None, - description="A specific Huawei Cloud access key ID.", - title="Huawei Cloud Access Key ID:", + default=None, + description = "A specific Huawei Cloud access key ID.", + title = "Huawei Cloud Access Key ID:", ) huawei_cloud_secret_access_key: Optional[SecretStr] = Field( - default=None, - description="A specific Huawei Cloud secret access key.", - title="Huawei Cloud Access Key Secret:", + default=None, + description = "A specific Huawei Cloud secret access key.", + title = "Huawei Cloud Access Key Secret:", ) huawei_cloud_project_id: Optional[SecretStr] = Field( - default=None, - description="A specific Huawei Cloud project id.", - title="Huawei Cloud project id", + default=None, + description = "A specific Huawei Cloud project id.", + title = "Huawei Cloud project id", ) huawei_cloud_security_token: Optional[SecretStr] = Field( - default=None, - description="SecurityToken in the temporary access key, " - "You can select a temporary token or AK/SK for authentication", - title="Huawei Cloud Security Token", + default=None, + description = "SecurityToken in the temporary access key, " + "You can select a temporary token or AK/SK for authentication", + title = "Huawei Cloud Security Token", ) region_id: Optional[str] = Field( - default=None, - title="region id", + default=None, + title = "region id", ) huawei_cloud_dew_parameters: Dict = Field( - default=None, - description="Extra parameters for using dew.", - title="dew_parameters", + default=None, + description = "Extra parameters for using dew.", + title = "dew_parameters", ) @dataclass class CreateSecretOptions: - def __init__(self,name=None,kms_key_id=None,description=None,secret_binary=None,secret_string=None, - secret_type=None,auto_rotation=None,rotation_period=None,rotation_config=None, - event_subscriptions=None,enterprise_project_id=None): + def __init__(self, name=None, kms_key_id=None, description=None, secret_binary=None, secret_string=None, + secret_type=None, auto_rotation=None, rotation_period=None, rotation_config=None, + event_subscriptions=None, enterprise_project_id=None): self.name = name self.kms_key_id = kms_key_id self.description = description @@ -75,7 +75,7 @@ class DewBlock(Block): @dataclass class CreatekeyOptions: - def __init__(self, key_alias=None, key_spec=None, key_usage=None, key_description=None, + def __init__(self, key_alias=None, key_spec=None, key_usage=None, key_description=None, origin=None, enterprise_project_id=None, sequence=None, keystore_id=None): self.key_alias = key_alias self.key_spec = key_spec @@ -86,27 +86,19 @@ class DewBlock(Block): self.sequence = sequence self.keystore_id = keystore_id - key_alias=None - key_spec=None - key_usage=None - key_description=None - origin=None - enterprise_project_id=None - sequence=None - keystore_id=None - @dataclass class ImportkeyMaterialOptions: - key_id=None - import_token=None - encrypted_key_material=None, - encrypted_privatekey=None - expiration_time=None - sequence=None + def __init__(self, key_id=None, import_token=None, encrypted_key_material=None, encrypted_privatekey=None, expiration_time=None, sequence=None): + self.key_id=key_id + self.import_token=import_token + self.encrypted_key_material=encrypted_key_material, + self.encrypted_privatekey=encrypted_privatekey + self.expiration_time=expiration_time + self.sequence=sequence @dataclass class CreateGrantOptions: - def __init__(self, key_id=None, grantee_principal=None, listOperationsbody=None, name=None, + def __init__(self, key_id=None, grantee_principal=None, listOperationsbody=None, name=None, grantee_principal_type=None, retiring_principal=None, sequence=None): self.key_id = key_id self.grantee_principal = grantee_principal @@ -116,17 +108,9 @@ class DewBlock(Block): self.retiring_principal = retiring_principal self.sequence = sequence - key_id=None - grantee_principal=None - listOperationsbody=None - name=None - retiring_principal=None - grantee_principal_type=None - sequence=None - @dataclass class ValidateSignatureOptions: - def __init__(self, asymmetric_key_id=None, message=None, signing_algorithm=None, signature=None, + def __init__(self, asymmetric_key_id=None, message=None, signing_algorithm=None, signature=None, message_type=None, sequence=None): self.asymmetric_key_id = asymmetric_key_id self.message = message @@ -137,7 +121,7 @@ class DewBlock(Block): @dataclass class ListKeysOptions: - def __init__(self, limit=None, marker=None, key_state=None, key_spec=None, enterprise_project_id=None, + def __init__(self, limit=None, marker=None, key_state=None, key_spec=None, enterprise_project_id=None, sequence=None): self.limit = limit self.marker = marker @@ -158,7 +142,7 @@ class DewBlock(Block): @dataclass class AssociateKeypairOptions: - def __init__(self,keypair_name=None,type=None, key=None,id =None,disable_password = False,port=None): + def __init__(self, keypair_name=None, type=None, key=None, id =None, disable_password = False, port=None): self.keypair_name = keypair_name self.type = type self.key = key @@ -168,7 +152,7 @@ class DewBlock(Block): @dataclass class BatchAssociateKeypairOptions: - def __init__(self,keypair_name=None,type=None, key=None,id=None,disable_password = False,port=None): + def __init__(self, keypair_name=None, type=None, key=None, id=None, disable_password = False, port=None): self.keypair_name = keypair_name self.type = type self.key = key @@ -178,8 +162,8 @@ class DewBlock(Block): @dataclass class UpdateSecretOptions: - def __init__(self,kms_key_id=None,secret_name=None,description=None,auto_rotation=None, - rotation_period=None,listEventSubscriptionsbody=None): + def __init__(self, kms_key_id=None, secret_name=None, description=None, auto_rotation=None, + rotation_period=None, listEventSubscriptionsbody=None): self.kms_key_id = kms_key_id self.secret_name = secret_name self.description = description @@ -189,7 +173,7 @@ class DewBlock(Block): @dataclass class CreateSecretEventOptions: - def __init__(self,target_type=None,target_id=None,target_name=None,event_name=None,state=None,event_types=None): + def __init__(self, target_type=None, target_id=None, target_name=None, event_name=None, state=None, event_types=None): self.target_type = target_type self.target_id = target_id self.target_name = target_name @@ -199,8 +183,8 @@ class DewBlock(Block): @dataclass class ListResourceInstancesOptions: - def __init__(self,resource_instances=None,values=None,key=None,limit=None,offset=None,action=None, - matches=None,sequence=None): + def __init__(self, resource_instances=None, values=None, key=None, limit=None, offset=None, action=None, + matches=None, sequence=None): self.resource_instances = resource_instances self.values = values self.key = key @@ -212,7 +196,7 @@ class DewBlock(Block): @dataclass class ListKmsByTagsOptions: - def __init__(self, key=None, values=None, limit=None, offset=None, action=None, tags=None, matches=None, + def __init__(self, key=None, values=None, limit=None, offset=None, action=None, tags=None, matches=None, sequence=None): self.key = key self.values = values @@ -223,11 +207,11 @@ class DewBlock(Block): self.matches = matches self.sequence = sequence - def __init__(self, *args, **kwargs): - self._dew_client = DewClient(region_id=kwargs.get('region_id'), - ak=kwargs.get('huawei_cloud_access_key_id'), - sk=kwargs.get('huawei_cloud_secret_access_key'), - project_id=kwargs.get('huawei_cloud_project_id')) + def __init__(self, **kwargs): + self._dew_client = DewClient(region_id = kwargs.get('region_id'), + ak = kwargs.get('huawei_cloud_access_key_id'), + sk = kwargs.get('huawei_cloud_secret_access_key'), + project_id = kwargs.get('huawei_cloud_project_id')) self.dew_parameters = kwargs.get('huawei_cloud_dew_parameters') @property @@ -259,21 +243,21 @@ class DewBlock(Block): try: request = CreateKeyRequest() request.body = CreateKeyRequestBody( - key_alias=options.key_alias, - key_spec=options.key_spec, - key_usage=options.key_usage, - key_description=options.key_description, - origin=options.origin, - enterprise_project_id=options.enterprise_project_id, - sequence=options.sequence, - keystore_id=options.keystore_id + key_alias = options.key_alias, + key_spec = options.key_spec, + key_usage = options.key_usage, + key_description = options.key_description, + origin = options.origin, + enterprise_project_id = options.enterprise_project_id, + sequence = options.sequence, + keystore_id = options.keystore_id ) response = self._dew_client.kms_client.create_key(request) self.logger.debug("Created key") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -291,16 +275,16 @@ class DewBlock(Block): try: request = DeleteKeyRequest() request.body = ScheduleKeyDeletionRequestBody( - key_id=key_id, - pending_days=pending_days, - sequence=sequence + key_id = key_id, + pending_days = pending_days, + sequence = sequence ) response = self._dew_client.kms_client.delete_key(request) self.logger.debug("Successfully delete_key") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -316,15 +300,15 @@ class DewBlock(Block): try: request = DisableKeyRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self._dew_client.kms_client.disable_key(request) self.logger.info("Successfully disable_key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -340,15 +324,15 @@ class DewBlock(Block): try: request = EnableKeyRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self._dew_client.kms_client.enable_key(request) self.logger.info("Successfully enable_key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -361,20 +345,20 @@ class DewBlock(Block): For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str :key_alias: Non default master key alias, ranging from 1 to 255 characters, satisfies regular matching - "^[a-zA-Z0-9:/_-]{1,255}$"and cannot have the suffix "/default". + "^[a-zA-Z0-9:/_-]{1, 255}$"and cannot have the suffix "/default". :type key_alias: str """ try: request = UpdateKeyAliasRequest() request.body = UpdateKeyAliasRequestBody( - key_alias=key_alias, - key_id=key_id, - sequence=sequence + key_alias = key_alias, + key_id = key_id, + sequence = sequence ) response = self._dew_client.kms_client.update_key_alias(request) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -392,16 +376,16 @@ class DewBlock(Block): try: request = UpdateKeyDescriptionRequest() request.body = UpdateKeyDescriptionRequestBody( - key_id=key_id, - key_description=key_description, - sequence=sequence + key_id = key_id, + key_description = key_description, + sequence = sequence ) response = self._dew_client.kms_client.update_key_description(request) self.logger.info("Successfully update_key_description:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -417,15 +401,15 @@ class DewBlock(Block): try: request = CancelKeyDeletionRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self._dew_client.kms_client.cancel_key_deletion(request) self.logger.info("Successfully canccel key daletion:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -441,17 +425,17 @@ class DewBlock(Block): try: request = CreateDatakeyRequest() request.body = CreateDatakeyRequestBody( - key_id=key_id, - key_spec=key_spec, - datakey_length=datakey_length, - sequence=sequence + key_id = key_id, + key_spec = key_spec, + datakey_length = datakey_length, + sequence = sequence ) response = self._dew_client.kms_client.create_datakey(request) self.logger.info("Successfully created datakey:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -467,17 +451,17 @@ class DewBlock(Block): try: request = CreateDatakeyWithoutPlaintextRequest() request.body = CreateDatakeyRequestBody( - key_id=key_id, - key_spec=key_spec, - datakey_length=datakey_length, - sequence=sequence + key_id = key_id, + key_spec = key_spec, + datakey_length = datakey_length, + sequence = sequence ) response = self._dew_client.kms_client.create_datakey_without_plaintext(request) self.logger.info("Successfully created datakey without plaintext:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -493,15 +477,15 @@ class DewBlock(Block): try: request = CreateRandomRequest() request.body = GenRandomRequestBody( - random_data_length=random_data_length, - sequence=sequence + random_data_length = random_data_length, + sequence = sequence ) response = self._dew_client.kms_client.create_random(request) self.logger.info("Successfully created random:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -524,10 +508,10 @@ class DewBlock(Block): try: request = DecryptDatakeyRequest() request.body = DecryptDatakeyRequestBody( - key_id=key_id, - cipher_text=cipher_text, - datakey_cipher_length=datakey_cipher_length, - sequence=sequence + key_id = key_id, + cipher_text = cipher_text, + datakey_cipher_length = datakey_cipher_length, + sequence = sequence ) response = self._dew_client.kms_client.decrypt_datakey(request) self.logger.info("Successfully decrypted datakey:") @@ -535,7 +519,7 @@ class DewBlock(Block): return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -548,7 +532,7 @@ class DewBlock(Block): For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str - :param plain_ Text: When CMK is AES, SHA256 (32 bytes) for DEK plaintext and DEK plaintext; When CMK is SM4, + :param plain_ Text: When CMK is AES, SHA256 (32 bytes) for DEK plaintext and DEK plaintext; When CMK is SM4, both DEK plaintext and SM3 (32 bytes) of DEK plaintext are represented as hexadecimal strings. :type plain_ Text: str @@ -558,17 +542,17 @@ class DewBlock(Block): try: request = EncryptDatakeyRequest() request.body = EncryptDatakeyRequestBody( - key_id=key_id, - plain_text=plain_text, - datakey_plain_length=datakey_plain_length, - sequence=sequence + key_id = key_id, + plain_text = plain_text, + datakey_plain_length = datakey_plain_length, + sequence = sequence ) response = self._dew_client.kms_client.encrypt_datakey(request) self.logger.info("Successfully encrypted datakey:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -580,23 +564,23 @@ class DewBlock(Block): :key_id: Key ID, 36 bytes, satisfies regular matching“^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$”. For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str - :wrapping_algorithm: Key material encryption algorithm, enumeration as follows: - RSAES_ OAEP_ SHA_ 256- SM2_ ENCRYPT, + :wrapping_algorithm: Key material encryption algorithm, enumeration as follows: - RSAES_ OAEP_ SHA_ 256- SM2_ ENCRYPT, some offices do not support this import type :type wrapping_ algorithm: str """ try: request = CreateParametersForImportRequest() request.body = GetParametersForImportRequestBody( - key_id=key_id, - wrapping_algorithm=wrapping_algorithm, - sequence=sequence + key_id = key_id, + wrapping_algorithm = wrapping_algorithm, + sequence = sequence ) response = self._dew_client.kms_client.create_parameters_for_import(request) self.logger.info("Successfully created parameters for import:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -612,15 +596,15 @@ class DewBlock(Block): try: request = DeleteImportedKeyMaterialRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self._dew_client.kms_client.delete_imported_key_material(request) self.logger.info("Successfully deleted imported key material:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -634,29 +618,29 @@ class DewBlock(Block): For example: 0d0466b0-e727-4d9c-b35d-f84bb474a37f. :type key_id: str - :param import_token: Key import token, in base64 format, that satisfies regular matching "^[0-9a-zA-Z+/=]{200,6144}$". + :param import_token: Key import token, in base64 format, that satisfies regular matching "^[0-9a-zA-Z+/ = ]{200, 6144}$". :type import_ Token: str :param encrypted_key_material: The encrypted symmetric key material, in base64 format, satisfies regular matching - "^[0-9a-zA-Z+/=]{344,360}$". If importing an asymmetric key, this parameter is the temporary intermediate key used to encrypt the private key. + "^[0-9a-zA-Z+/ = ]{344, 360}$". If importing an asymmetric key, this parameter is the temporary intermediate key used to encrypt the private key. :type encrypted_key_material: str """ try: request = ImportKeyMaterialRequest() request.body = ImportKeyMaterialRequestBody( - key_id=options.key_id, - import_token=options.import_token, - encrypted_key_material=options.encrypted_key_material, - encrypted_privatekey=options.encrypted_privatekey, - expiration_time=options.expiration_time, - sequence=options.sequence + key_id = options.key_id, + import_token = options.import_token, + encrypted_key_material = options.encrypted_key_material, + encrypted_privatekey = options.encrypted_privatekey, + expiration_time = options.expiration_time, + sequence = options.sequence ) response = self._dew_client.kms_client.import_key_material(request) self.logger.info("Successfully imported key material:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -674,7 +658,7 @@ class DewBlock(Block): For example:0d0466b00d0466b00d0466b00d0466b0 :type grantee_principal: str - :param operations: List of authorized and allowed operations. Valid values: "create datakey", "create datakey without plaintext", + :param operations: List of authorized and allowed operations. Valid values: "create datakey", "create datakey without plaintext", "encrypt-datakey", "decrypt-datakey", "describe-key", "create-grant", "retain grant", "encrypt-data", "decrypt-data". The valid values cannot be just "create-grant"- "create-datakey" Create data key - "Create datakey without plaintext" Create data key without plaintext - "encrypt-datakey" Encrypt data key - "decrypt-datakey" Decrypt data key - "describe-key" Query key information - @@ -684,20 +668,20 @@ class DewBlock(Block): try: request = CreateGrantRequest() request.body = CreateGrantRequestBody( - key_id=options.key_id, - grantee_principal=options.grantee_principal, - operations=options.listOperationsbody, - grantee_principal_type=options.grantee_principal_type, - retiring_principal=options.retiring_principal, - name=options.name, - sequence=options.sequence + key_id = options.key_id, + grantee_principal = options.grantee_principal, + operations = options.listOperationsbody, + grantee_principal_type = options.grantee_principal_type, + retiring_principal = options.retiring_principal, + name = options.name, + sequence = options.sequence ) response = self._dew_client.kms_client.create_grant(request) self.logger.info("Successfully create grant:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -708,16 +692,16 @@ class DewBlock(Block): try: request = ListRetirableGrantsRequest() request.body = ListRetirableGrantsRequestBody( - limit=limit, - marker=marker, - sequence=sequence + limit = limit, + marker = marker, + sequence = sequence ) response = self._dew_client.kms_client.list_retirable_grants(request) self.logger.info("Successfully list retirable grants:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -734,24 +718,24 @@ class DewBlock(Block): try: request = ListGrantsRequest() request.body = ListGrantsRequestBody( - key_id=key_id, - limit=limit, - marker=marker, - sequence=sequence + key_id = key_id, + limit = limit, + marker = marker, + sequence = sequence ) response = self._dew_client.kms_client.list_grants(request) self.logger.info("Successfully list grants:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e def cancel_self_grant(self, key_id=None, grant_id=None, sequence=None): """ Retirement authorization means that the authorized user no longer has the right to operate the authorization key. - For example, if user A authorizes user B to operate key A/key, and authorizes user C to revoke the authorization, + For example, if user A authorizes user B to operate key A/key, and authorizes user C to revoke the authorization, then users A, B, and C can all retire the authorization. After retiring the authorization, user B can no longer use key A. Args: @@ -767,16 +751,16 @@ class DewBlock(Block): try: request = CancelSelfGrantRequest() request.body = RevokeGrantRequestBody( - grant_id=grant_id, - key_id=key_id, - sequence=sequence + grant_id = grant_id, + key_id = key_id, + sequence = sequence ) response = self._dew_client.kms_client.cancel_self_grant(request) self.logger.info("Successfully cancel self grant:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -797,16 +781,16 @@ class DewBlock(Block): try: request = CancelGrantRequest() request.body = RevokeGrantRequestBody( - grant_id=grant_id, - key_id=key_id, - sequence=sequence + grant_id = grant_id, + key_id = key_id, + sequence = sequence ) response = self._dew_client.kms_client.cancel_grant(request) self.logger.info("Successfully cancel grant:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -816,24 +800,24 @@ class DewBlock(Block): Args: :param cipher_text: Encrypted data ciphertext. The value is the cipher in the encrypted data result. - The value of text satisfies regular matching "^[0-9a-zA-Z+/=]{128,5648}$". + The value of text satisfies regular matching "^[0-9a-zA-Z+/ = ]{128, 5648}$". :type cipher_text: str """ try: request = DecryptDataRequest() request.body = DecryptDataRequestBody( - cipher_text=cipher_text, - encryption_algorithm=encryption_algorithm, - key_id=key_id, - sequence=sequence + cipher_text = cipher_text, + encryption_algorithm = encryption_algorithm, + key_id = key_id, + sequence = sequence ) response = self._dew_client.kms_client.decrypt_data(request) self.logger.info("Successfully decrypted data:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -854,17 +838,17 @@ class DewBlock(Block): try: request = EncryptDataRequest() request.body = EncryptDataRequestBody( - plain_text=plain_text, - key_id=key_id, - encryption_algorithm=encryption_algorithm, - sequence=sequence + plain_text = plain_text, + key_id = key_id, + encryption_algorithm = encryption_algorithm, + sequence = sequence ) response = self._dew_client.kms_client.encrypt_data(request) self.logger.info("Successfully encrypted data:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -890,18 +874,18 @@ class DewBlock(Block): try: request = SignRequest() request.body = SignRequestBody( - signing_algorithm=signing_algorithm, - message=message, - key_id=asymmetric_key_id, - message_type=message_type, - sequence=sequence + signing_algorithm = signing_algorithm, + message = message, + key_id = asymmetric_key_id, + message_type = message_type, + sequence = sequence ) response = self._dew_client.kms_client.sign(request) self.logger.info("Successfully sign:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -930,19 +914,19 @@ class DewBlock(Block): try: request = ValidateSignatureRequest() request.body = VerifyRequestBody( - key_id=options.asymmetric_key_id, - message=options.message, - signature=options.signature, - signing_algorithm=options.signing_algorithm, - message_type=options.message_type, - sequence=options.sequence + key_id = options.asymmetric_key_id, + message = options.message, + signature = options.signature, + signing_algorithm = options.signing_algorithm, + message_type = options.message_type, + sequence = options.sequence ) response = self._dew_client.kms_client.validate_signature(request) self.logger.info("Successfully list validate signature:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -959,15 +943,15 @@ class DewBlock(Block): try: request = ListKeyDetailRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self._dew_client.kms_client.list_key_detail(request) self.logger.info("Successfully list key detail:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -978,18 +962,18 @@ class DewBlock(Block): try: request = ListKeysRequest() request.body = ListKeysRequestBody( - limit=options.limit, - marker=options.marker, - key_state=options.key_state, - key_spec=options.key_spec, - enterprise_project_id=options.enterprise_project_id, - sequence=options.sequence + limit = options.limit, + marker = options.marker, + key_state = options.key_state, + key_spec = options.key_spec, + enterprise_project_id = options.enterprise_project_id, + sequence = options.sequence ) response = self._dew_client.kms_client.list_keys(request) self.logger.info(json.dumps(response.to_dict()).replace('}', '}\n')) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1006,15 +990,15 @@ class DewBlock(Block): try: request = ShowPublicKeyRequest() request.body = OperateKeyRequestBody( - key_id=asymmetric_key_id, - sequence=sequence + key_id = asymmetric_key_id, + sequence = sequence ) response = self._dew_client.kms_client.show_public_key(request) self.logger.info("Successfully show public key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1029,7 +1013,7 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1044,7 +1028,7 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1057,13 +1041,13 @@ class DewBlock(Block): :type version_id: str """ try: - request = ShowVersionRequest(version_id=version_id) + request = ShowVersionRequest(version_id = version_id) response = self._dew_client.kms_client.show_version(request) self.logger.info("Successfully show_version:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1078,7 +1062,7 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1095,15 +1079,15 @@ class DewBlock(Block): try: request = DisableKeyRotationRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self._dew_client.kms_client.disable_key_rotation(request) self.logger.info("Successfully disable key rotation:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1120,15 +1104,15 @@ class DewBlock(Block): try: request = EnableKeyRotationRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self._dew_client.kms_client.enable_key_rotation(request) self.logger.info("Successfully enable key rotation:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1145,15 +1129,15 @@ class DewBlock(Block): try: request = ShowKeyRotationStatusRequest() request.body = OperateKeyRequestBody( - key_id=key_id, - sequence=sequence + key_id = key_id, + sequence = sequence ) response = self._dew_client.kms_client.show_key_rotation_status(request) self.logger.info("Successfully show key rotation status:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1168,23 +1152,23 @@ class DewBlock(Block): :type key_id: str :param rotation_interval: Rotation period, an integer with a range of values from 30 to 365. - The cycle range is set based on the frequency of key usage. If the frequency of key usage is high, + The cycle range is set based on the frequency of key usage. If the frequency of key usage is high, it is recommended to set it to a short cycle; On the contrary, set it to long cycle. :type rotation_interval: int """ try: request = UpdateKeyRotationIntervalRequest() request.body = UpdateKeyRotationIntervalRequestBody( - rotation_interval=rotation_interval, - key_id=key_id, - sequence=sequence + rotation_interval = rotation_interval, + key_id = key_id, + sequence = sequence ) response = self._dew_client.kms_client.update_key_rotation_interval(request) self.logger.info("Successfully update key rotation interval:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1200,22 +1184,22 @@ class DewBlock(Block): try: request = CreateKeypairRequest() key_pair_body = CreateKeypairAction( - name=options.name, - type=options.type, - public_key=options.public_key, - scope=options.scope, - user_id=options.user_id, - key_protection=options.key_protection + name = options.name, + type = options.type, + public_key = options.public_key, + scope = options.scope, + user_id = options.user_id, + key_protection = options.key_protection ) request.body = CreateKeypairRequestBody( - keypair=key_pair_body + keypair = key_pair_body ) response = self._dew_client.kps_client.create_keypair(request) self.logger.info("Successfully created keypair:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1224,13 +1208,13 @@ class DewBlock(Block): Query SSH key pair list. """ try: - request = ListKeypairsRequest(limit=limit, marker=marker) + request = ListKeypairsRequest(limit = limit, marker = marker) response = self._dew_client.kps_client.list_keypairs(request) self.logger.info("Successfully list keypairs:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1243,13 +1227,13 @@ class DewBlock(Block): :type keypair_name: str """ try: - request = ClearPrivateKeyRequest(keypair_name=keypair_name) + request = ClearPrivateKeyRequest(keypair_name = keypair_name) response = self._dew_client.kps_client.clear_private_key(request) self.logger.info("Successfully cleared private key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1275,25 +1259,25 @@ class DewBlock(Block): try: request = ImportPrivateKeyRequest() encryption_key_protection = Encryption( - type=type, - kms_key_name=kms_key_name + type = type, + kms_key_name = kms_key_name ) key_protection_keypair = ImportPrivateKeyProtection( - private_key=private_key, - encryption=encryption_key_protection + private_key = private_key, + encryption = encryption_key_protection ) key_pair_body = ImportPrivateKeyKeypairBean( - name = name, - key_protection=key_protection_keypair, - user_id=user_id + name = name, + key_protection = key_protection_keypair, + user_id = user_id ) - request.body = ImportPrivateKeyRequestBody(keypair=key_pair_body) + request.body = ImportPrivateKeyRequestBody(keypair = key_pair_body) response = self._dew_client.kps_client.import_private_key(request) self.logger.info("Successfully import_private_key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1306,13 +1290,13 @@ class DewBlock(Block): :type keypair_name: str """ try: - request = ListKeypairDetailRequest(keypair_name=keypair_name) + request = ListKeypairDetailRequest(keypair_name = keypair_name) response = self._dew_client.kps_client.list_keypair_detail(request) self.logger.info("Successfully list_keypair_detail") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1329,20 +1313,20 @@ class DewBlock(Block): """ try: request = UpdateKeypairDescriptionRequest( - keypair_name=keypair_name + keypair_name = keypair_name ) key_pair_body = UpdateKeypairDescriptionReq( - description=description + description = description ) request.body = UpdateKeypairDescriptionRequestBody( - keypair=key_pair_body + keypair = key_pair_body ) response = self._dew_client.kps_client.update_keypair_description(request) self.logger.info("Successfully update keypair description:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1356,13 +1340,13 @@ class DewBlock(Block): try: request = ExportPrivateKeyRequest() key_pair_body = KeypairBean(name = name) - request.body = ExportPrivateKeyRequestBody(keypair=key_pair_body) + request.body = ExportPrivateKeyRequestBody(keypair = key_pair_body) response = self._dew_client.kps_client.export_private_key(request) self.logger.info("Successfully exported private key:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1375,13 +1359,13 @@ class DewBlock(Block): :type keypair_name: str """ try: - request = DeleteKeypairRequest(keypair_name=keypair_name) + request = DeleteKeypairRequest(keypair_name = keypair_name) response = self._dew_client.kps_client.delete_keypair(request) self.logger.info("Successfully deleted keypair") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1407,16 +1391,16 @@ class DewBlock(Block): """ try: request = AssociateKeypairRequest() - auth_server = Auth(type=options.type, key=options.key) + auth_server = Auth(type = options.type, key = options.key) server_body = EcsServerInfo( - auth=auth_server, - id=options.id, - disable_password=options.disable_password, - port=options.port + auth = auth_server, + id = options.id, + disable_password = options.disable_password, + port = options.port ) request.body = AssociateKeypairRequestBody( - server=server_body, - keypair_name=options.keypair_name + server = server_body, + keypair_name = options.keypair_name ) response = self._dew_client.kps_client.associate_keypair(request) self.logger.info("Successfully associate_keypair:") @@ -1424,7 +1408,7 @@ class DewBlock(Block): return response except exceptions.ClientRequestException as e: self.logger.info(id) - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1443,47 +1427,47 @@ class DewBlock(Block): request = BatchAssociateKeypairRequest() list_batch_keypairs_body = [] if isinstance(options.keypair_name, list): - for t, k, i, d, p, kn in zip(options.type, options.key, options.id, options.disable_password, + for t, k, i, d, p, kn in zip(options.type, options.key, options.id, options.disable_password, options.port, options.keypair_name): auth_server = Auth( - type=t if t is not None else None, - key=k if k is not None else None + type = t if t is not None else None, + key = k if k is not None else None ) server_satch_keypairs = EcsServerInfo( - id=i if i is not None else None, - auth=auth_server, - disable_password=d if d is not None else None, - port=p if p is not None else None + id = i if i is not None else None, + auth = auth_server, + disable_password = d if d is not None else None, + port = p if p is not None else None ) list_batch_keypairs_body.append(AssociateKeypairRequestBody( - keypair_name=kn if kn is not None else None, - server=server_satch_keypairs + keypair_name = kn if kn is not None else None, + server = server_satch_keypairs )) else: auth_server = Auth( - type=options.type, - key=options.key + type = options.type, + key = options.key ) server_satch_keypairs = EcsServerInfo( - id=options.id, - auth=auth_server, - disable_password=options.disable_password, - port=options.port + id = options.id, + auth = auth_server, + disable_password = options.disable_password, + port = options.port ) list_batch_keypairs_body.append(AssociateKeypairRequestBody( - keypair_name=options.keypair_name, - server=server_satch_keypairs + keypair_name = options.keypair_name, + server = server_satch_keypairs )) request.body = BatchAssociateKeypairRequestBody( - batch_keypairs=list_batch_keypairs_body + batch_keypairs = list_batch_keypairs_body ) response = self._dew_client.kps_client.batch_associate_keypair(request) self.logger.info("Successfully batch_associate_keypair:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1498,11 +1482,11 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e - def delete_failed_task(self, task_id): + def delete_failed_task(self, task_id=None): """ Delete failed tasks. @@ -1511,14 +1495,14 @@ class DewBlock(Block): """ try: request = DeleteFailedTaskRequest( - task_id=task_id, + task_id = task_id, ) response = self._dew_client.kps_client.delete_failed_task(request) self.logger.info("Successfully delete_failed_task:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1530,15 +1514,15 @@ class DewBlock(Block): """ try: request = DisassociateKeypairRequest() - auth_server = Auth(type=type, key=key) - server_body = DisassociateEcsServerInfo(id=id, auth=auth_server) - request.body = DisassociateKeypairRequestBody(server=server_body) + auth_server = Auth(type = type, key = key) + server_body = DisassociateEcsServerInfo(id = id, auth = auth_server) + request.body = DisassociateKeypairRequestBody(server = server_body) response = self._dew_client.kps_client.disassociate_keypair(request) self.logger.info("Successfully disassociate_keypair:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1555,7 +1539,7 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1568,13 +1552,13 @@ class DewBlock(Block): :type task_id: str """ try: - request = ListKeypairTaskRequest(task_id=task_id) + request = ListKeypairTaskRequest(task_id = task_id) response = self._dew_client.kps_client.list_keypair_task(request) self.logger.info("Successfully list_keypair_task:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1591,7 +1575,7 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1606,30 +1590,30 @@ class DewBlock(Block): Args: :param name: The name of the credential to be created. Constraint: The value range is 1 to 64 characters, satisfying the regular matching - "^[a-zA-Z0-9_-]{1,64}$". + "^[a-zA-Z0-9_-]{1, 64}$". :type name: str """ try: request = CreateSecretRequest() request.body = CreateSecretRequestBody( - secret_string=options.secret_string, - kms_key_id=options.kms_key_id, - name=options.name, - description=options.description, - secret_binary=options.secret_binary, - secret_type=options.secret_type, - auto_rotation=options.auto_rotation, - rotation_period=options.rotation_period, - rotation_config=options.rotation_config, - event_subscriptions=options.event_subscriptions, - enterprise_project_id=options.enterprise_project_id + secret_string = options.secret_string, + kms_key_id = options.kms_key_id, + name = options.name, + description = options.description, + secret_binary = options.secret_binary, + secret_type = options.secret_type, + auto_rotation = options.auto_rotation, + rotation_period = options.rotation_period, + rotation_config = options.rotation_config, + event_subscriptions = options.event_subscriptions, + enterprise_project_id = options.enterprise_project_id ) response = self._dew_client.cms_client.create_secret(request) self.logger.info("Successfully create_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1642,13 +1626,13 @@ class DewBlock(Block): :type secret_name: str """ try: - request = DownloadSecretBlobRequest(secret_name=secret_name) + request = DownloadSecretBlobRequest(secret_name = secret_name) response = self._dew_client.cms_client.download_secret_blob(request) self.logger.info("Successfully download_secret_blob:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1666,7 +1650,7 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1679,17 +1663,17 @@ class DewBlock(Block): :type secret_name: str """ try: - request = ShowSecretRequest(secret_name=secret_name) + request = ShowSecretRequest(secret_name = secret_name) response = self._dew_client.cms_client.show_secret(request) self.logger.info("Successfully show_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e - def update_secret(self, options: UpdateSecretOptions): + def update_secret(self, options:UpdateSecretOptions): """ Update metadata information for specified credentials. @@ -1700,11 +1684,11 @@ class DewBlock(Block): try: request = UpdateSecretRequest() request.body = UpdateSecretRequestBody( - event_subscriptions=options.listEventSubscriptionsbody, - description=options.description, - kms_key_id=options.kms_key_id, - auto_rotation=options.auto_rotation, - rotation_period=options.rotation_period, + event_subscriptions = options.listEventSubscriptionsbody, + description = options.description, + kms_key_id = options.kms_key_id, + auto_rotation = options.auto_rotation, + rotation_period = options.rotation_period, ) request.secret_name = options.secret_name response = self._dew_client.cms_client.update_secret(request) @@ -1713,7 +1697,7 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1725,7 +1709,7 @@ class DewBlock(Block): Args: :param name: The name of the newly created event notification. Constraint: The value range is 1 to 64 - characters, satisfying the regular matching "^ [a-zA-Z0-9_ -] {1,64} $". + characters, satisfying the regular matching "^ [a-zA-Z0-9_ -] {1, 64} $". :type name: str :param event_types:he basic event list for this event notification, with the following basic event types. @@ -1748,23 +1732,23 @@ class DewBlock(Block): """ try: request = CreateSecretEventRequest() - notification_body=Notification( - target_type=options.target_type, - target_id=options.target_id, - target_name=options.target_name + notification_body = Notification( + target_type = options.target_type, + target_id = options.target_id, + target_name = options.target_name ) request.body = CreateSecretEventRequestBody( - notification=notification_body, - state=options.state, - event_types=options.event_types, - name=options.event_name, + notification = notification_body, + state = options.state, + event_types = options.event_types, + name = options.event_name, ) response = self._dew_client.cms_client.create_secret_event(request) self.logger.info("Successfully create_secret_event:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1779,13 +1763,13 @@ class DewBlock(Block): """ try: request = UploadSecretBlobRequest() - request.body = UploadSecretBlobRequestBody(secret_blob=secret_blob) + request.body = UploadSecretBlobRequestBody(secret_blob = secret_blob) response = self._dew_client.cms_client.upload_secret_blob(request) self.logger.info("Successfully upload_secret_blob:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1800,13 +1784,13 @@ class DewBlock(Block): :type secret_name: str """ try: - request = RotateSecretRequest(secret_name=secret_name) + request = RotateSecretRequest(secret_name = secret_name) response = self._dew_client.cms_client.rotate_secret(request) self.logger.info("Successfully rotate_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1819,13 +1803,13 @@ class DewBlock(Block): :type secret_name: str """ try: - request = RestoreSecretRequest(secret_name=secret_name) + request = RestoreSecretRequest(secret_name = secret_name) response = self._dew_client.cms_client.restore_secret(request) self.logger.info("Successfully restore_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1842,16 +1826,16 @@ class DewBlock(Block): :type recovery_ Window_ In_ Days: int """ try: - request = DeleteSecretForScheduleRequest(secret_name=secret_name) + request = DeleteSecretForScheduleRequest(secret_name = secret_name) request.body = DeleteSecretForScheduleRequestBody( - recovery_window_in_days=recovery_window_in_days + recovery_window_in_days = recovery_window_in_days ) response = self._dew_client.cms_client.delete_secret_for_schedule(request) self.logger.info("Successfully delete_secret_for_schedule:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1864,17 +1848,17 @@ class DewBlock(Block): :type secret_name: str """ try: - request = DeleteSecretRequest(secret_name=secret_name) + request = DeleteSecretRequest(secret_name = secret_name) response = self._dew_client.cms_client.delete_secret(request) self.logger.info("Successfully delete_secret:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e - def create_secret_version(self, secret_name=None, secret_binary=None, + def create_secret_version(self, secret_name=None, secret_binary=None, secret_string=None, version_stages=None, expire_time=None): """ Create a new credential version within the specified credentials to encrypt and store the new credential values. @@ -1886,19 +1870,19 @@ class DewBlock(Block): :type secret_name: str """ try: - request = CreateSecretVersionRequest(secret_name=secret_name) + request = CreateSecretVersionRequest(secret_name = secret_name) request.body = CreateSecretVersionRequestBody( - secret_string=secret_string, - secret_binary=secret_binary, - version_stages=version_stages, - expire_time=expire_time + secret_string = secret_string, + secret_binary = secret_binary, + version_stages = version_stages, + expire_time = expire_time ) response = self._dew_client.cms_client.create_secret_version(request) self.logger.info("Successfully create_secret_version:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1920,13 +1904,13 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e def show_secret_version(self, secret_name=None, version_id=None): """ - Query the information of the specified credential version and the plaintext credential value in the version, + Query the information of the specified credential version and the plaintext credential value in the version, only the credentials with ENABLED status can be queried. The latest version of the credentials can be accessed through/v1/{project_id}/secrets/{secretname}/versions/latest (i.e. assigning {version _id} in the current interface URL as latest) @@ -1946,7 +1930,7 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1973,14 +1957,14 @@ class DewBlock(Block): request.version_id = version_id request.secret_name = secret_name request.body = UpdateVersionRequestBody( - expire_time=expire_time + expire_time = expire_time ) response = self._dew_client.cms_client.update_version(request) self.logger.info("Successfully update_version:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -1996,13 +1980,13 @@ class DewBlock(Block): :type stage_name: str """ try: - request = ShowSecretStageRequest(secret_name=secret_name, stage_name=stage_name) + request = ShowSecretStageRequest(secret_name = secret_name, stage_name = stage_name) response = self._dew_client.cms_client.show_secret_stage(request) self.logger.info("Successfully show_secret_stage:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2014,18 +1998,18 @@ class DewBlock(Block): :param secret_name: The name of the credential. :type secret_name: str - :param stage_name: The name of the credential version status.matching '^[a-zA-Z0-9_-]{1,64}$' + :param stage_name: The name of the credential version status.matching '^[a-zA-Z0-9_-]{1, 64}$' :type stage_name: str """ try: - request = UpdateSecretStageRequest(secret_name=secret_name, stage_name=stage_name) - request.body = UpdateSecretStageRequestBody(version_id=version_id) + request = UpdateSecretStageRequest(secret_name = secret_name, stage_name = stage_name) + request.body = UpdateSecretStageRequestBody(version_id = version_id) response = self._dew_client.cms_client.update_secret_stage(request) self.logger.info("Successfully update_secret_stage:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2041,13 +2025,13 @@ class DewBlock(Block): :type stage_name: str """ try: - request = DeleteSecretStageRequest(secret_name=secret_name, stage_name=stage_name) + request = DeleteSecretStageRequest(secret_name = secret_name, stage_name = stage_name) response = self._dew_client.cms_client.delete_secret_stage(request) self.logger.info("Successfully delete_secret_stage:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2069,27 +2053,27 @@ class DewBlock(Block): :type action: str """ try: - request = BatchCreateOrDeleteTagsRequest(secret_id=secret_id) + request = BatchCreateOrDeleteTagsRequest(secret_id = secret_id) listTagsbody = [] if isinstance(key, list): for k, v in zip(key, value): - listTagsbody.append(TagItem(key=k, - value=v if v is not None else None)) + listTagsbody.append(TagItem(key = k, + value = v if v is not None else None)) else: - listTagsbody.append(TagItem(key=key, value=value)) + listTagsbody.append(TagItem(key = key, value = value)) request.body = BatchCreateOrDeleteTagsRequestBody( - action=action, - tags=listTagsbody, - sequence=sequence + action = action, + tags = listTagsbody, + sequence = sequence ) response = self._dew_client.cms_client.batch_create_or_delete_tags(request) self.logger.info("Successfully batch_create_or_delete_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2108,20 +2092,20 @@ class DewBlock(Block): :type key: str """ try: - request = CreateSecretTagRequest(secret_id=secret_id) + request = CreateSecretTagRequest(secret_id = secret_id) tagbody = TagItem( - key=key, - value=value, + key = key, + value = value, ) request.body = CreateSecretTagRequestBody( - tag=tagbody + tag = tagbody ) response = self._dew_client.cms_client.create_secret_tag(request) self.logger.info("Successfully create_secret_tag:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2140,13 +2124,13 @@ class DewBlock(Block): :type key: str """ try: - request = DeleteSecretTagRequest(secret_id=secret_id, key=key) + request = DeleteSecretTagRequest(secret_id = secret_id, key = key) response = self._dew_client.cms_client.delete_secret_tag(request) self.logger.info("Successfully delete_secret_tag:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2161,7 +2145,7 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2178,28 +2162,28 @@ class DewBlock(Block): :type resource_instances: str """ try: - request = ListResourceInstancesRequest(resource_instances=options.resource_instances) + request = ListResourceInstancesRequest(resource_instances = options.resource_instances) listTagsbody = [] if isinstance(options.key, list): for k, v in zip(options.key, options.values): - listTagsbody.append(Tag(key=k if k is not None else None, - values=v if v is not None else None)) + listTagsbody.append(Tag(key = k if k is not None else None, + values = v if v is not None else None)) else: - listTagsbody.append(Tag(key=options.key, values=options.values)) + listTagsbody.append(Tag(key = options.key, values = options.values)) request.body = ListResourceInstancesRequestBody( - tags=listTagsbody if options.key is not None else None, - action=options.action, - matches=options.matches, - sequence=options.sequence, - offset=options.offset, - limit=options.limit + tags = listTagsbody if options.key is not None else None, + action = options.action, + matches = options.matches, + sequence = options.sequence, + offset = options.offset, + limit = options.limit ) response = self._dew_client.cms_client.list_resource_instances(request) self.logger.info("Successfully list_resource_instances:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2212,19 +2196,19 @@ class DewBlock(Block): :type secret_id: str """ try: - request = ListSecretTagsRequest(secret_id=secret_id) + request = ListSecretTagsRequest(secret_id = secret_id) response = self._dew_client.cms_client.list_secret_tags(request) self.logger.info("Successfully list_secret_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e def delete_secret_event(self, event_name=None): """ - Immediately delete the specified event and cannot be restored. If there is a credential reference in the event, + Immediately delete the specified event and cannot be restored. If there is a credential reference in the event, it cannot be deleted. Please dissociate it first. Args: @@ -2232,13 +2216,13 @@ class DewBlock(Block): :type event_name: str """ try: - request = DeleteSecretEventRequest(event_name=event_name) + request = DeleteSecretEventRequest(event_name = event_name) response = self._dew_client.cms_client.delete_secret_event(request) self.logger.info("Successfully delete_secret_event:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2255,7 +2239,7 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2268,19 +2252,19 @@ class DewBlock(Block): :type event_name: str """ try: - request = ShowSecretEventRequest(event_name=event_name) + request = ShowSecretEventRequest(event_name = event_name) response = self._dew_client.cms_client.show_secret_event(request) self.logger.info("Successfully show_secret_event:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e def update_secret_event(self, event_name=None, target_type=None, target_id=None, target_name=None): """ - Update metadata information for specified events. The metadata that supports updates includes event enable status, + Update metadata information for specified events. The metadata that supports updates includes event enable status, basic type list, and notification topic. Args: @@ -2288,21 +2272,21 @@ class DewBlock(Block): :type event_name: str """ try: - request = UpdateSecretEventRequest(event_name=event_name) - notificationbody=Notification( - target_type=target_type, - target_id=target_id, - target_name=target_name + request = UpdateSecretEventRequest(event_name = event_name) + notificationbody = Notification( + target_type = target_type, + target_id = target_id, + target_name = target_name ) request.body = UpdateSecretEventRequestBody( - notification=notificationbody + notification = notificationbody ) response = self._dew_client.cms_client.update_secret_event(request) self.logger.info("Successfully update_secret_event:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2312,15 +2296,15 @@ class DewBlock(Block): """ try: request = ListNotificationRecordsRequest( - limit=limit, - marker=marker + limit = limit, + marker = marker ) response = self._dew_client.cms_client.list_notification_records(request) self.logger.info("Successfully list_notification_records:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2341,26 +2325,26 @@ class DewBlock(Block): :type key: list[str] """ try: - request = BatchCreateKmsTagsRequest(key_id=key_id) + request = BatchCreateKmsTagsRequest(key_id = key_id) listTagsbody = [] if isinstance(key, list): if not isinstance(value, list): value = [value] for k, v in zip(key, value): - listTagsbody.append(TagItem(key=k, - value=v if v is not None else None)) + listTagsbody.append(TagItem(key = k, + value = v if v is not None else None)) else: - listTagsbody.append(TagItem(key=key, value=value)) + listTagsbody.append(TagItem(key = key, value = value)) request.body = BatchCreateKmsTagsRequestBody( - action=action, - tags=listTagsbody + action = action, + tags = listTagsbody ) response = self._dew_client.kms_client.batch_create_kms_tags(request) self.logger.info("Successfully batch_create_kms_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2379,20 +2363,20 @@ class DewBlock(Block): :type key: str """ try: - request = CreateKmsTagRequest(key_id=key_id) + request = CreateKmsTagRequest(key_id = key_id) tagbody = TagItem( - key=key, - value=value + key = key, + value = value ) request.body = CreateKmsTagRequestBody( - tag=tagbody + tag = tagbody ) response = self._dew_client.kms_client.create_kms_tag(request) self.logger.info("Successfully create_kms_tag:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2407,7 +2391,7 @@ class DewBlock(Block): self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2422,13 +2406,13 @@ class DewBlock(Block): :type key: str """ try: - request = DeleteTagRequest(key_id=key_id, key=key) + request = DeleteTagRequest(key_id = key_id, key = key) response = self._dew_client.kms_client.delete_tag(request) self.logger.info("Successfully delete_tag:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2437,28 +2421,28 @@ class DewBlock(Block): Query key instances. Filter through tags to query detailed information about the specified user's master key. """ try: - request = ListKmsByTagsRequest(resource_instances="resource_instances") + request = ListKmsByTagsRequest(resource_instances = "resource_instances") listTagsbody = [] if isinstance(options.key, list): for k, v in zip(options.key, options.values): - listTagsbody.append(Tag(key=k if k is not None else None, - values=v if v is not None else None)) + listTagsbody.append(Tag(key = k if k is not None else None, + values = v if v is not None else None)) else: - listTagsbody.append(Tag(key=options.key, values=options.values)) + listTagsbody.append(Tag(key = options.key, values = options.values)) request.body = ListKmsByTagsRequestBody( - tags=listTagsbody if options.key is not None else None, - action=options.action, - offset=options.offset, - limit=options.limit, - sequence=options.sequence, - matches=options.matches + tags = listTagsbody if options.key is not None else None, + action = options.action, + offset = options.offset, + limit = options.limit, + sequence = options.sequence, + matches = options.matches ) response = self._dew_client.kms_client.list_kms_by_tags(request) self.logger.info("Successfully list_kms_by_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2471,13 +2455,13 @@ class DewBlock(Block): :type key_id: str """ try: - request = ShowKmsTagsRequest(key_id=key_id) + request = ShowKmsTagsRequest(key_id = key_id) response = self._dew_client.kms_client.show_kms_tags(request) self.logger.info("Successfully show_kms_tags:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e @@ -2487,7 +2471,7 @@ class DewBlock(Block): Args: :param keystore_alias: Exclusive key repository alias, with a value range of 1 to 255 characters, satisfies regular matching - "^[a-zA-Z0-9:/_-]{1,255}$", and does not have the same name as existing exclusive key repository aliases. + "^[a-zA-Z0-9:/_-]{1, 255}$", and does not have the same name as existing exclusive key repository aliases. :type keystore_alias: str :param hsm_cluster_id: The DHSM cluster ID requires that the cluster has not yet created a dedicated key repository. :type hsm_cluster_id: str @@ -2497,15 +2481,15 @@ class DewBlock(Block): try: request = CreateKeyStoreRequest() request.body = CreateKeyStoreRequestBody( - hsm_ca_cert=hsm_ca_cert, - hsm_cluster_id=hsm_cluster_id, - keystore_alias=keystore_alias + hsm_ca_cert = hsm_ca_cert, + hsm_cluster_id = hsm_cluster_id, + keystore_alias = keystore_alias ) response = self._dew_client.kms_client.create_key_store(request) self.logger.info("Successfully create_key_store:") self.logger.info(response) return response except exceptions.ClientRequestException as e: - self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id},\ + self.logger.error(f"status_code = {e.status_code}, request_id = {e.request_id}, \ error_code = {e.error_code}, error_msg = {e.error_msg}") return e -- Gitee