From 1820c0153702f75458bd7c86318bec61604fac11 Mon Sep 17 00:00:00 2001 From: Andrea Lin Date: Fri, 17 Nov 2017 11:31:28 -0800 Subject: [PATCH] First Bigtable gapic gen for php (#731) * first bigtable gapic gen for php * adding bigtable admin * ran PHPCBF to format php files; added first draft of Bigtable/composer.json * copied over bigtable from api-client-staging after regening using php-cs-fixer:2.2.7; ran phpcbf style fixer on result * adding docs/contents/cloud-bigtable.json * spacing in composer.json * adding bigtable VERSION and in composer.json * updated manifest.json with bigtable and to master * adding readme for bigtable * use master's version of non-bigtable things * update to master * update tests/ to master * update to master * update to master * update to master * new line * bump version to master's proto-client (0.26) * removed extraneous comma in cloud-bigtable.json * manifest.json: bigtable/readme * added readme * updating json files --- composer.json | 2 + docs/contents/cloud-bigtable.json | 25 + docs/manifest.json | 9 + .../Admin/V2/BigtableInstanceAdminClient.php | 41 + .../Admin/V2/BigtableTableAdminClient.php | 41 + .../BigtableInstanceAdminGapicClient.php | 1238 +++++++++++++++++ .../Gapic/BigtableTableAdminGapicClient.php | 809 +++++++++++ ...bigtable_instance_admin_client_config.json | 78 ++ .../bigtable_table_admin_client_config.json | 56 + src/Bigtable/LICENSE | 202 +++ src/Bigtable/README.md | 16 + src/Bigtable/V2/BigtableClient.php | 41 + src/Bigtable/V2/Gapic/BigtableGapicClient.php | 800 +++++++++++ src/Bigtable/V2/README.md | 16 + .../V2/resources/bigtable_client_config.json | 50 + src/Bigtable/VERSION | 1 + src/Bigtable/composer.json | 24 + 17 files changed, 3449 insertions(+) create mode 100644 docs/contents/cloud-bigtable.json create mode 100644 src/Bigtable/Admin/V2/BigtableInstanceAdminClient.php create mode 100644 src/Bigtable/Admin/V2/BigtableTableAdminClient.php create mode 100644 src/Bigtable/Admin/V2/Gapic/BigtableInstanceAdminGapicClient.php create mode 100644 src/Bigtable/Admin/V2/Gapic/BigtableTableAdminGapicClient.php create mode 100644 src/Bigtable/Admin/V2/resources/bigtable_instance_admin_client_config.json create mode 100644 src/Bigtable/Admin/V2/resources/bigtable_table_admin_client_config.json create mode 100644 src/Bigtable/LICENSE create mode 100644 src/Bigtable/README.md create mode 100644 src/Bigtable/V2/BigtableClient.php create mode 100644 src/Bigtable/V2/Gapic/BigtableGapicClient.php create mode 100644 src/Bigtable/V2/README.md create mode 100644 src/Bigtable/V2/resources/bigtable_client_config.json create mode 100644 src/Bigtable/VERSION create mode 100644 src/Bigtable/composer.json diff --git a/composer.json b/composer.json index 48ce98baaa58..6b117eb98e1f 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,7 @@ "google cloud platform", "google cloud", "cloud", + "bigtable", "bigquery", "big query", "datastore", @@ -63,6 +64,7 @@ "phpseclib/phpseclib": "^2" }, "replace": { + "google/cloud-bigtable": "0.1.0", "google/cloud-bigquery": "0.3.1", "google/cloud-core": "1.13.1", "google/cloud-datastore": "1.1.0", diff --git a/docs/contents/cloud-bigtable.json b/docs/contents/cloud-bigtable.json new file mode 100644 index 000000000000..5d8287d146b4 --- /dev/null +++ b/docs/contents/cloud-bigtable.json @@ -0,0 +1,25 @@ +{ + "title": "Bigtable", + "pattern": "bigtable\/\\w{1,}", + "services": [{ + "title": "BigtableClient", + "type": "bigtable/readme" + }, { + "title": "v2", + "type": "bigtable/v2/readme", + "patterns": [ + "bigtable/v2/\\w{1,}", + "bigtable/admin/v2/\\w{1,}" + ], + "nav": [{ + "title": "BigtableClient", + "type": "bigtable/v2/bigtableclient" + }, { + "title": "BigtableInstanceAdminClient", + "type": "bigtable/admin/v2/bigtableinstanceadminclient" + }, { + "title": "BigtableTableAdminClient", + "type": "bigtable/admin/v2/bigtabletableadminclient" + }] + }] +} diff --git a/docs/manifest.json b/docs/manifest.json index 25a414fefd07..c33471688905 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -72,6 +72,15 @@ "master" ] }, + { + "id": "cloud-bigtable", + "name": "google/cloud-bigtable", + "defaultService": "bigtable/readme", + "versions": [ + "v0.1.0", + "master" + ] + }, { "id": "cloud-bigquery", "name": "google/cloud-bigquery", diff --git a/src/Bigtable/Admin/V2/BigtableInstanceAdminClient.php b/src/Bigtable/Admin/V2/BigtableInstanceAdminClient.php new file mode 100644 index 000000000000..b88afa3da803 --- /dev/null +++ b/src/Bigtable/Admin/V2/BigtableInstanceAdminClient.php @@ -0,0 +1,41 @@ +projectName('[PROJECT]'); + * $instanceId = ''; + * $instance = new Instance(); + * $clusters = []; + * $operationResponse = $bigtableInstanceAdminClient->createInstance($formattedParent, $instanceId, $instance, $clusters); + * $operationResponse->pollUntilComplete(); + * if ($operationResponse->operationSucceeded()) { + * $result = $operationResponse->getResult(); + * // doSomethingWith($result) + * } else { + * $error = $operationResponse->getError(); + * // handleError($error) + * } + * + * // OR start the operation, keep the operation name, and resume later + * $operationResponse = $bigtableInstanceAdminClient->createInstance($formattedParent, $instanceId, $instance, $clusters); + * $operationName = $operationResponse->getName(); + * // ... do other work + * $newOperationResponse = $bigtableInstanceAdminClient->resumeOperation($operationName, 'createInstance'); + * while (!$newOperationResponse->isDone()) { + * // ... do other work + * $newOperationResponse->reload(); + * } + * if ($newOperationResponse->operationSucceeded()) { + * $result = $newOperationResponse->getResult(); + * // doSomethingWith($result) + * } else { + * $error = $newOperationResponse->getError(); + * // handleError($error) + * } + * } finally { + * $bigtableInstanceAdminClient->close(); + * } + * ``` + * + * Many parameters require resource names to be formatted in a particular way. To assist + * with these names, this class includes a format method for each type of name, and additionally + * a parseName method to extract the individual identifiers contained within formatted names + * that are returned by the API. + * + * @experimental + */ +class BigtableInstanceAdminGapicClient +{ + /** + * The default address of the service. + */ + const SERVICE_ADDRESS = 'bigtableadmin.googleapis.com'; + + /** + * The default port of the service. + */ + const DEFAULT_SERVICE_PORT = 443; + + /** + * The name of the code generator, to be included in the agent header. + */ + const CODEGEN_NAME = 'gapic'; + + /** + * The code generator version, to be included in the agent header. + */ + const CODEGEN_VERSION = '0.0.5'; + + private static $projectNameTemplate; + private static $instanceNameTemplate; + private static $clusterNameTemplate; + private static $locationNameTemplate; + private static $pathTemplateMap; + private static $gapicVersion; + private static $gapicVersionLoaded = false; + + protected $grpcCredentialsHelper; + protected $bigtableInstanceAdminStub; + private $scopes; + private $defaultCallSettings; + private $descriptors; + private $operationsClient; + + private static function getProjectNameTemplate() + { + if (self::$projectNameTemplate == null) { + self::$projectNameTemplate = new PathTemplate('projects/{project}'); + } + + return self::$projectNameTemplate; + } + + private static function getInstanceNameTemplate() + { + if (self::$instanceNameTemplate == null) { + self::$instanceNameTemplate = new PathTemplate('projects/{project}/instances/{instance}'); + } + + return self::$instanceNameTemplate; + } + + private static function getClusterNameTemplate() + { + if (self::$clusterNameTemplate == null) { + self::$clusterNameTemplate = new PathTemplate('projects/{project}/instances/{instance}/clusters/{cluster}'); + } + + return self::$clusterNameTemplate; + } + + private static function getLocationNameTemplate() + { + if (self::$locationNameTemplate == null) { + self::$locationNameTemplate = new PathTemplate('projects/{project}/locations/{location}'); + } + + return self::$locationNameTemplate; + } + + private static function getPathTemplateMap() + { + if (self::$pathTemplateMap == null) { + self::$pathTemplateMap = [ + 'project' => self::getProjectNameTemplate(), + 'instance' => self::getInstanceNameTemplate(), + 'cluster' => self::getClusterNameTemplate(), + 'location' => self::getLocationNameTemplate(), + ]; + } + + return self::$pathTemplateMap; + } + + private static function getLongRunningDescriptors() + { + return [ + 'createInstance' => [ + 'operationReturnType' => '\Google\Bigtable\Admin\V2\Instance', + 'metadataReturnType' => '\Google\Bigtable\Admin\V2\CreateInstanceMetadata', + ], + 'createCluster' => [ + 'operationReturnType' => '\Google\Bigtable\Admin\V2\Cluster', + 'metadataReturnType' => '\Google\Bigtable\Admin\V2\CreateClusterMetadata', + ], + 'updateCluster' => [ + 'operationReturnType' => '\Google\Bigtable\Admin\V2\Cluster', + 'metadataReturnType' => '\Google\Bigtable\Admin\V2\UpdateClusterMetadata', + ], + ]; + } + + private static function getGapicVersion() + { + if (!self::$gapicVersionLoaded) { + if (file_exists(__DIR__.'/../VERSION')) { + self::$gapicVersion = trim(file_get_contents(__DIR__.'/../VERSION')); + } elseif (class_exists(Version::class)) { + self::$gapicVersion = Version::VERSION; + } + self::$gapicVersionLoaded = true; + } + + return self::$gapicVersion; + } + + /** + * Formats a string containing the fully-qualified path to represent + * a project resource. + * + * @param string $project + * + * @return string The formatted project resource. + * @experimental + */ + public static function projectName($project) + { + return self::getProjectNameTemplate()->render([ + 'project' => $project, + ]); + } + + /** + * Formats a string containing the fully-qualified path to represent + * a instance resource. + * + * @param string $project + * @param string $instance + * + * @return string The formatted instance resource. + * @experimental + */ + public static function instanceName($project, $instance) + { + return self::getInstanceNameTemplate()->render([ + 'project' => $project, + 'instance' => $instance, + ]); + } + + /** + * Formats a string containing the fully-qualified path to represent + * a cluster resource. + * + * @param string $project + * @param string $instance + * @param string $cluster + * + * @return string The formatted cluster resource. + * @experimental + */ + public static function clusterName($project, $instance, $cluster) + { + return self::getClusterNameTemplate()->render([ + 'project' => $project, + 'instance' => $instance, + 'cluster' => $cluster, + ]); + } + + /** + * Formats a string containing the fully-qualified path to represent + * a location resource. + * + * @param string $project + * @param string $location + * + * @return string The formatted location resource. + * @experimental + */ + public static function locationName($project, $location) + { + return self::getLocationNameTemplate()->render([ + 'project' => $project, + 'location' => $location, + ]); + } + + /** + * Parses a formatted name string and returns an associative array of the components in the name. + * The following name formats are supported: + * Template: Pattern + * - project: projects/{project} + * - instance: projects/{project}/instances/{instance} + * - cluster: projects/{project}/instances/{instance}/clusters/{cluster} + * - location: projects/{project}/locations/{location}. + * + * The optional $template argument can be supplied to specify a particular pattern, and must + * match one of the templates listed above. If no $template argument is provided, or if the + * $template argument does not match one of the templates listed, then parseName will check + * each of the supported templates, and return the first match. + * + * @param string $formattedName The formatted name string + * @param string $template Optional name of template to match + * + * @return array An associative array from name component IDs to component values. + * + * @throws ValidationException If $formattedName could not be matched. + * @experimental + */ + public static function parseName($formattedName, $template = null) + { + $templateMap = self::getPathTemplateMap(); + + if ($template) { + if (!isset($templateMap[$template])) { + throw new ValidationException("Template name $template does not exist"); + } + + return $templateMap[$template]->match($formattedName); + } + + foreach ($templateMap as $templateName => $pathTemplate) { + try { + return $pathTemplate->match($formattedName); + } catch (ValidationException $ex) { + // Swallow the exception to continue trying other path templates + } + } + throw new ValidationException("Input did not match any known format. Input: $formattedName"); + } + + /** + * Return an OperationsClient object with the same endpoint as $this. + * + * @return \Google\GAX\LongRunning\OperationsClient + * @experimental + */ + public function getOperationsClient() + { + return $this->operationsClient; + } + + /** + * Resume an existing long running operation that was previously started + * by a long running API method. If $methodName is not provided, or does + * not match a long running API method, then the operation can still be + * resumed, but the OperationResponse object will not deserialize the + * final response. + * + * @param string $operationName The name of the long running operation + * @param string $methodName The name of the method used to start the operation + * + * @return \Google\GAX\OperationResponse + * @experimental + */ + public function resumeOperation($operationName, $methodName = null) + { + $lroDescriptors = self::getLongRunningDescriptors(); + if (!is_null($methodName) && array_key_exists($methodName, $lroDescriptors)) { + $options = $lroDescriptors[$methodName]; + } else { + $options = []; + } + $operation = new OperationResponse($operationName, $this->getOperationsClient(), $options); + $operation->reload(); + + return $operation; + } + + /** + * Constructor. + * + * @param array $options { + * Optional. Options for configuring the service API wrapper. + * + * @type string $serviceAddress The domain name of the API remote host. + * Default 'bigtableadmin.googleapis.com'. + * @type mixed $port The port on which to connect to the remote host. Default 443. + * @type \Grpc\Channel $channel + * A `Channel` object to be used by gRPC. If not specified, a channel will be constructed. + * @type \Grpc\ChannelCredentials $sslCreds + * A `ChannelCredentials` object for use with an SSL-enabled channel. + * Default: a credentials object returned from + * \Grpc\ChannelCredentials::createSsl() + * NOTE: if the $channel optional argument is specified, then this argument is unused. + * @type bool $forceNewChannel + * If true, this forces gRPC to create a new channel instead of using a persistent channel. + * Defaults to false. + * NOTE: if the $channel optional argument is specified, then this option is unused. + * @type \Google\Auth\CredentialsLoader $credentialsLoader + * A CredentialsLoader object created using the Google\Auth library. + * @type array $scopes A string array of scopes to use when acquiring credentials. + * Defaults to the scopes for the Cloud Bigtable Admin API. + * @type string $clientConfigPath + * Path to a JSON file containing client method configuration, including retry settings. + * Specify this setting to specify the retry behavior of all methods on the client. + * By default this settings points to the default client config file, which is provided + * in the resources folder. The retry settings provided in this option can be overridden + * by settings in $retryingOverride + * @type array $retryingOverride + * An associative array in which the keys are method names (e.g. 'createFoo'), and + * the values are retry settings to use for that method. The retry settings for each + * method can be a {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on {@see Google\GAX\RetrySettings} + * for example usage. Passing a value of null is equivalent to a value of + * ['retriesEnabled' => false]. Retry settings provided in this setting override the + * settings in $clientConfigPath. + * } + * @experimental + */ + public function __construct($options = []) + { + $defaultOptions = [ + 'serviceAddress' => self::SERVICE_ADDRESS, + 'port' => self::DEFAULT_SERVICE_PORT, + 'scopes' => [ + 'https://www.googleapis.com/auth/bigtable.admin', + 'https://www.googleapis.com/auth/bigtable.admin.cluster', + 'https://www.googleapis.com/auth/bigtable.admin.instance', + 'https://www.googleapis.com/auth/bigtable.admin.table', + 'https://www.googleapis.com/auth/cloud-bigtable.admin', + 'https://www.googleapis.com/auth/cloud-bigtable.admin.cluster', + 'https://www.googleapis.com/auth/cloud-bigtable.admin.table', + 'https://www.googleapis.com/auth/cloud-platform', + 'https://www.googleapis.com/auth/cloud-platform.read-only', + ], + 'retryingOverride' => null, + 'libName' => null, + 'libVersion' => null, + 'clientConfigPath' => __DIR__.'/../resources/bigtable_instance_admin_client_config.json', + ]; + $options = array_merge($defaultOptions, $options); + + if (array_key_exists('operationsClient', $options)) { + $this->operationsClient = $options['operationsClient']; + } else { + $operationsClientOptions = $options; + unset($operationsClientOptions['retryingOverride']); + unset($operationsClientOptions['clientConfigPath']); + $this->operationsClient = new OperationsClient($operationsClientOptions); + } + + $gapicVersion = $options['libVersion'] ?: self::getGapicVersion(); + + $headerDescriptor = new AgentHeaderDescriptor([ + 'libName' => $options['libName'], + 'libVersion' => $options['libVersion'], + 'gapicVersion' => $gapicVersion, + ]); + + $defaultDescriptors = ['headerDescriptor' => $headerDescriptor]; + $this->descriptors = [ + 'createInstance' => $defaultDescriptors, + 'getInstance' => $defaultDescriptors, + 'listInstances' => $defaultDescriptors, + 'updateInstance' => $defaultDescriptors, + 'deleteInstance' => $defaultDescriptors, + 'createCluster' => $defaultDescriptors, + 'getCluster' => $defaultDescriptors, + 'listClusters' => $defaultDescriptors, + 'updateCluster' => $defaultDescriptors, + 'deleteCluster' => $defaultDescriptors, + ]; + $longRunningDescriptors = self::getLongRunningDescriptors(); + foreach ($longRunningDescriptors as $method => $longRunningDescriptor) { + $this->descriptors[$method]['longRunningDescriptor'] = $longRunningDescriptor + ['operationsClient' => $this->operationsClient]; + } + + $clientConfigJsonString = file_get_contents($options['clientConfigPath']); + $clientConfig = json_decode($clientConfigJsonString, true); + $this->defaultCallSettings = + CallSettings::load( + 'google.bigtable.admin.v2.BigtableInstanceAdmin', + $clientConfig, + $options['retryingOverride'] + ); + + $this->scopes = $options['scopes']; + + $createStubOptions = []; + if (array_key_exists('sslCreds', $options)) { + $createStubOptions['sslCreds'] = $options['sslCreds']; + } + $this->grpcCredentialsHelper = new GrpcCredentialsHelper($options); + + $createBigtableInstanceAdminStubFunction = function ($hostname, $opts, $channel) { + return new BigtableInstanceAdminGrpcClient($hostname, $opts, $channel); + }; + if (array_key_exists('createBigtableInstanceAdminStubFunction', $options)) { + $createBigtableInstanceAdminStubFunction = $options['createBigtableInstanceAdminStubFunction']; + } + $this->bigtableInstanceAdminStub = $this->grpcCredentialsHelper->createStub($createBigtableInstanceAdminStubFunction); + } + + /** + * Create an instance within a project. + * + * Sample code: + * ``` + * try { + * $bigtableInstanceAdminClient = new BigtableInstanceAdminClient(); + * $formattedParent = $bigtableInstanceAdminClient->projectName('[PROJECT]'); + * $instanceId = ''; + * $instance = new Instance(); + * $clusters = []; + * $operationResponse = $bigtableInstanceAdminClient->createInstance($formattedParent, $instanceId, $instance, $clusters); + * $operationResponse->pollUntilComplete(); + * if ($operationResponse->operationSucceeded()) { + * $result = $operationResponse->getResult(); + * // doSomethingWith($result) + * } else { + * $error = $operationResponse->getError(); + * // handleError($error) + * } + * + * // OR start the operation, keep the operation name, and resume later + * $operationResponse = $bigtableInstanceAdminClient->createInstance($formattedParent, $instanceId, $instance, $clusters); + * $operationName = $operationResponse->getName(); + * // ... do other work + * $newOperationResponse = $bigtableInstanceAdminClient->resumeOperation($operationName, 'createInstance'); + * while (!$newOperationResponse->isDone()) { + * // ... do other work + * $newOperationResponse->reload(); + * } + * if ($newOperationResponse->operationSucceeded()) { + * $result = $newOperationResponse->getResult(); + * // doSomethingWith($result) + * } else { + * $error = $newOperationResponse->getError(); + * // handleError($error) + * } + * } finally { + * $bigtableInstanceAdminClient->close(); + * } + * ``` + * + * @param string $parent The unique name of the project in which to create the new instance. + * Values are of the form `projects/`. + * @param string $instanceId The ID to be used when referring to the new instance within its project, + * e.g., just `myinstance` rather than + * `projects/myproject/instances/myinstance`. + * @param Instance $instance The instance to create. + * Fields marked `OutputOnly` must be left blank. + * @param array $clusters The clusters to be created within the instance, mapped by desired + * cluster ID, e.g., just `mycluster` rather than + * `projects/myproject/instances/myinstance/clusters/mycluster`. + * Fields marked `OutputOnly` must be left blank. + * Currently exactly one cluster must be specified. + * @param array $optionalArgs { + * Optional. + * + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\GAX\OperationResponse + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function createInstance($parent, $instanceId, $instance, $clusters, $optionalArgs = []) + { + $request = new CreateInstanceRequest(); + $request->setParent($parent); + $request->setInstanceId($instanceId); + $request->setInstance($instance); + $request->setClusters($clusters); + + $defaultCallSettings = $this->defaultCallSettings['createInstance']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableInstanceAdminStub, + 'CreateInstance', + $mergedSettings, + $this->descriptors['createInstance'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Gets information about an instance. + * + * Sample code: + * ``` + * try { + * $bigtableInstanceAdminClient = new BigtableInstanceAdminClient(); + * $formattedName = $bigtableInstanceAdminClient->instanceName('[PROJECT]', '[INSTANCE]'); + * $response = $bigtableInstanceAdminClient->getInstance($formattedName); + * } finally { + * $bigtableInstanceAdminClient->close(); + * } + * ``` + * + * @param string $name The unique name of the requested instance. Values are of the form + * `projects//instances/`. + * @param array $optionalArgs { + * Optional. + * + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\Bigtable\Admin\V2\Instance + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function getInstance($name, $optionalArgs = []) + { + $request = new GetInstanceRequest(); + $request->setName($name); + + $defaultCallSettings = $this->defaultCallSettings['getInstance']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableInstanceAdminStub, + 'GetInstance', + $mergedSettings, + $this->descriptors['getInstance'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Lists information about instances in a project. + * + * Sample code: + * ``` + * try { + * $bigtableInstanceAdminClient = new BigtableInstanceAdminClient(); + * $formattedParent = $bigtableInstanceAdminClient->projectName('[PROJECT]'); + * $response = $bigtableInstanceAdminClient->listInstances($formattedParent); + * } finally { + * $bigtableInstanceAdminClient->close(); + * } + * ``` + * + * @param string $parent The unique name of the project for which a list of instances is requested. + * Values are of the form `projects/`. + * @param array $optionalArgs { + * Optional. + * + * @type string $pageToken + * The value of `next_page_token` returned by a previous call. + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\Bigtable\Admin\V2\ListInstancesResponse + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function listInstances($parent, $optionalArgs = []) + { + $request = new ListInstancesRequest(); + $request->setParent($parent); + if (isset($optionalArgs['pageToken'])) { + $request->setPageToken($optionalArgs['pageToken']); + } + + $defaultCallSettings = $this->defaultCallSettings['listInstances']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableInstanceAdminStub, + 'ListInstances', + $mergedSettings, + $this->descriptors['listInstances'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Updates an instance within a project. + * + * Sample code: + * ``` + * try { + * $bigtableInstanceAdminClient = new BigtableInstanceAdminClient(); + * $formattedName = $bigtableInstanceAdminClient->instanceName('[PROJECT]', '[INSTANCE]'); + * $displayName = ''; + * $type = Type::TYPE_UNSPECIFIED; + * $response = $bigtableInstanceAdminClient->updateInstance($formattedName, $displayName, $type); + * } finally { + * $bigtableInstanceAdminClient->close(); + * } + * ``` + * + * @param string $name (`OutputOnly`) + * The unique name of the instance. Values are of the form + * `projects//instances/[a-z][a-z0-9\\-]+[a-z0-9]`. + * @param string $displayName The descriptive name for this instance as it appears in UIs. + * Can be changed at any time, but should be kept globally unique + * to avoid confusion. + * @param int $type The type of the instance. Defaults to `PRODUCTION`. + * For allowed values, use constants defined on {@see \Google\Bigtable\Admin\V2\Instance_Type} + * @param array $optionalArgs { + * Optional. + * + * @type int $state + * (`OutputOnly`) + * The current state of the instance. + * For allowed values, use constants defined on {@see \Google\Bigtable\Admin\V2\Instance_State} + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\Bigtable\Admin\V2\Instance + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function updateInstance($name, $displayName, $type, $optionalArgs = []) + { + $request = new Instance(); + $request->setName($name); + $request->setDisplayName($displayName); + $request->setType($type); + if (isset($optionalArgs['state'])) { + $request->setState($optionalArgs['state']); + } + + $defaultCallSettings = $this->defaultCallSettings['updateInstance']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableInstanceAdminStub, + 'UpdateInstance', + $mergedSettings, + $this->descriptors['updateInstance'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Delete an instance from a project. + * + * Sample code: + * ``` + * try { + * $bigtableInstanceAdminClient = new BigtableInstanceAdminClient(); + * $formattedName = $bigtableInstanceAdminClient->instanceName('[PROJECT]', '[INSTANCE]'); + * $bigtableInstanceAdminClient->deleteInstance($formattedName); + * } finally { + * $bigtableInstanceAdminClient->close(); + * } + * ``` + * + * @param string $name The unique name of the instance to be deleted. + * Values are of the form `projects//instances/`. + * @param array $optionalArgs { + * Optional. + * + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function deleteInstance($name, $optionalArgs = []) + { + $request = new DeleteInstanceRequest(); + $request->setName($name); + + $defaultCallSettings = $this->defaultCallSettings['deleteInstance']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableInstanceAdminStub, + 'DeleteInstance', + $mergedSettings, + $this->descriptors['deleteInstance'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Creates a cluster within an instance. + * + * Sample code: + * ``` + * try { + * $bigtableInstanceAdminClient = new BigtableInstanceAdminClient(); + * $formattedParent = $bigtableInstanceAdminClient->instanceName('[PROJECT]', '[INSTANCE]'); + * $clusterId = ''; + * $cluster = new Cluster(); + * $operationResponse = $bigtableInstanceAdminClient->createCluster($formattedParent, $clusterId, $cluster); + * $operationResponse->pollUntilComplete(); + * if ($operationResponse->operationSucceeded()) { + * $result = $operationResponse->getResult(); + * // doSomethingWith($result) + * } else { + * $error = $operationResponse->getError(); + * // handleError($error) + * } + * + * // OR start the operation, keep the operation name, and resume later + * $operationResponse = $bigtableInstanceAdminClient->createCluster($formattedParent, $clusterId, $cluster); + * $operationName = $operationResponse->getName(); + * // ... do other work + * $newOperationResponse = $bigtableInstanceAdminClient->resumeOperation($operationName, 'createCluster'); + * while (!$newOperationResponse->isDone()) { + * // ... do other work + * $newOperationResponse->reload(); + * } + * if ($newOperationResponse->operationSucceeded()) { + * $result = $newOperationResponse->getResult(); + * // doSomethingWith($result) + * } else { + * $error = $newOperationResponse->getError(); + * // handleError($error) + * } + * } finally { + * $bigtableInstanceAdminClient->close(); + * } + * ``` + * + * @param string $parent The unique name of the instance in which to create the new cluster. + * Values are of the form + * `projects//instances/`. + * @param string $clusterId The ID to be used when referring to the new cluster within its instance, + * e.g., just `mycluster` rather than + * `projects/myproject/instances/myinstance/clusters/mycluster`. + * @param Cluster $cluster The cluster to be created. + * Fields marked `OutputOnly` must be left blank. + * @param array $optionalArgs { + * Optional. + * + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\GAX\OperationResponse + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function createCluster($parent, $clusterId, $cluster, $optionalArgs = []) + { + $request = new CreateClusterRequest(); + $request->setParent($parent); + $request->setClusterId($clusterId); + $request->setCluster($cluster); + + $defaultCallSettings = $this->defaultCallSettings['createCluster']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableInstanceAdminStub, + 'CreateCluster', + $mergedSettings, + $this->descriptors['createCluster'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Gets information about a cluster. + * + * Sample code: + * ``` + * try { + * $bigtableInstanceAdminClient = new BigtableInstanceAdminClient(); + * $formattedName = $bigtableInstanceAdminClient->clusterName('[PROJECT]', '[INSTANCE]', '[CLUSTER]'); + * $response = $bigtableInstanceAdminClient->getCluster($formattedName); + * } finally { + * $bigtableInstanceAdminClient->close(); + * } + * ``` + * + * @param string $name The unique name of the requested cluster. Values are of the form + * `projects//instances//clusters/`. + * @param array $optionalArgs { + * Optional. + * + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\Bigtable\Admin\V2\Cluster + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function getCluster($name, $optionalArgs = []) + { + $request = new GetClusterRequest(); + $request->setName($name); + + $defaultCallSettings = $this->defaultCallSettings['getCluster']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableInstanceAdminStub, + 'GetCluster', + $mergedSettings, + $this->descriptors['getCluster'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Lists information about clusters in an instance. + * + * Sample code: + * ``` + * try { + * $bigtableInstanceAdminClient = new BigtableInstanceAdminClient(); + * $formattedParent = $bigtableInstanceAdminClient->instanceName('[PROJECT]', '[INSTANCE]'); + * $response = $bigtableInstanceAdminClient->listClusters($formattedParent); + * } finally { + * $bigtableInstanceAdminClient->close(); + * } + * ``` + * + * @param string $parent The unique name of the instance for which a list of clusters is requested. + * Values are of the form `projects//instances/`. + * Use ` = '-'` to list Clusters for all Instances in a project, + * e.g., `projects/myproject/instances/-`. + * @param array $optionalArgs { + * Optional. + * + * @type string $pageToken + * The value of `next_page_token` returned by a previous call. + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\Bigtable\Admin\V2\ListClustersResponse + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function listClusters($parent, $optionalArgs = []) + { + $request = new ListClustersRequest(); + $request->setParent($parent); + if (isset($optionalArgs['pageToken'])) { + $request->setPageToken($optionalArgs['pageToken']); + } + + $defaultCallSettings = $this->defaultCallSettings['listClusters']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableInstanceAdminStub, + 'ListClusters', + $mergedSettings, + $this->descriptors['listClusters'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Updates a cluster within an instance. + * + * Sample code: + * ``` + * try { + * $bigtableInstanceAdminClient = new BigtableInstanceAdminClient(); + * $formattedName = $bigtableInstanceAdminClient->clusterName('[PROJECT]', '[INSTANCE]', '[CLUSTER]'); + * $location = ''; + * $serveNodes = 0; + * $defaultStorageType = StorageType::STORAGE_TYPE_UNSPECIFIED; + * $operationResponse = $bigtableInstanceAdminClient->updateCluster($formattedName, $location, $serveNodes, $defaultStorageType); + * $operationResponse->pollUntilComplete(); + * if ($operationResponse->operationSucceeded()) { + * $result = $operationResponse->getResult(); + * // doSomethingWith($result) + * } else { + * $error = $operationResponse->getError(); + * // handleError($error) + * } + * + * // OR start the operation, keep the operation name, and resume later + * $operationResponse = $bigtableInstanceAdminClient->updateCluster($formattedName, $location, $serveNodes, $defaultStorageType); + * $operationName = $operationResponse->getName(); + * // ... do other work + * $newOperationResponse = $bigtableInstanceAdminClient->resumeOperation($operationName, 'updateCluster'); + * while (!$newOperationResponse->isDone()) { + * // ... do other work + * $newOperationResponse->reload(); + * } + * if ($newOperationResponse->operationSucceeded()) { + * $result = $newOperationResponse->getResult(); + * // doSomethingWith($result) + * } else { + * $error = $newOperationResponse->getError(); + * // handleError($error) + * } + * } finally { + * $bigtableInstanceAdminClient->close(); + * } + * ``` + * + * @param string $name (`OutputOnly`) + * The unique name of the cluster. Values are of the form + * `projects//instances//clusters/[a-z][-a-z0-9]*`. + * @param string $location (`CreationOnly`) + * The location where this cluster's nodes and storage reside. For best + * performance, clients should be located as close as possible to this cluster. + * Currently only zones are supported, so values should be of the form + * `projects//locations/`. + * @param int $serveNodes The number of nodes allocated to this cluster. More nodes enable higher + * throughput and more consistent performance. + * @param int $defaultStorageType (`CreationOnly`) + * The type of storage used by this cluster to serve its + * parent instance's tables, unless explicitly overridden. + * For allowed values, use constants defined on {@see \Google\Bigtable\Admin\V2\StorageType} + * @param array $optionalArgs { + * Optional. + * + * @type int $state + * (`OutputOnly`) + * The current state of the cluster. + * For allowed values, use constants defined on {@see \Google\Bigtable\Admin\V2\Cluster_State} + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\GAX\OperationResponse + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function updateCluster($name, $location, $serveNodes, $defaultStorageType, $optionalArgs = []) + { + $request = new Cluster(); + $request->setName($name); + $request->setLocation($location); + $request->setServeNodes($serveNodes); + $request->setDefaultStorageType($defaultStorageType); + if (isset($optionalArgs['state'])) { + $request->setState($optionalArgs['state']); + } + + $defaultCallSettings = $this->defaultCallSettings['updateCluster']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableInstanceAdminStub, + 'UpdateCluster', + $mergedSettings, + $this->descriptors['updateCluster'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Deletes a cluster from an instance. + * + * Sample code: + * ``` + * try { + * $bigtableInstanceAdminClient = new BigtableInstanceAdminClient(); + * $formattedName = $bigtableInstanceAdminClient->clusterName('[PROJECT]', '[INSTANCE]', '[CLUSTER]'); + * $bigtableInstanceAdminClient->deleteCluster($formattedName); + * } finally { + * $bigtableInstanceAdminClient->close(); + * } + * ``` + * + * @param string $name The unique name of the cluster to be deleted. Values are of the form + * `projects//instances//clusters/`. + * @param array $optionalArgs { + * Optional. + * + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function deleteCluster($name, $optionalArgs = []) + { + $request = new DeleteClusterRequest(); + $request->setName($name); + + $defaultCallSettings = $this->defaultCallSettings['deleteCluster']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableInstanceAdminStub, + 'DeleteCluster', + $mergedSettings, + $this->descriptors['deleteCluster'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Initiates an orderly shutdown in which preexisting calls continue but new + * calls are immediately cancelled. + * + * @experimental + */ + public function close() + { + $this->bigtableInstanceAdminStub->close(); + } + + private function createCredentialsCallback() + { + return $this->grpcCredentialsHelper->createCallCredentialsCallback(); + } +} diff --git a/src/Bigtable/Admin/V2/Gapic/BigtableTableAdminGapicClient.php b/src/Bigtable/Admin/V2/Gapic/BigtableTableAdminGapicClient.php new file mode 100644 index 000000000000..cde784fae164 --- /dev/null +++ b/src/Bigtable/Admin/V2/Gapic/BigtableTableAdminGapicClient.php @@ -0,0 +1,809 @@ +instanceName('[PROJECT]', '[INSTANCE]'); + * $tableId = ''; + * $table = new Table(); + * $response = $bigtableTableAdminClient->createTable($formattedParent, $tableId, $table); + * } finally { + * $bigtableTableAdminClient->close(); + * } + * ``` + * + * Many parameters require resource names to be formatted in a particular way. To assist + * with these names, this class includes a format method for each type of name, and additionally + * a parseName method to extract the individual identifiers contained within formatted names + * that are returned by the API. + * + * @experimental + */ +class BigtableTableAdminGapicClient +{ + /** + * The default address of the service. + */ + const SERVICE_ADDRESS = 'bigtableadmin.googleapis.com'; + + /** + * The default port of the service. + */ + const DEFAULT_SERVICE_PORT = 443; + + /** + * The name of the code generator, to be included in the agent header. + */ + const CODEGEN_NAME = 'gapic'; + + /** + * The code generator version, to be included in the agent header. + */ + const CODEGEN_VERSION = '0.0.5'; + + private static $instanceNameTemplate; + private static $tableNameTemplate; + private static $pathTemplateMap; + private static $gapicVersion; + private static $gapicVersionLoaded = false; + + protected $grpcCredentialsHelper; + protected $bigtableTableAdminStub; + private $scopes; + private $defaultCallSettings; + private $descriptors; + + private static function getInstanceNameTemplate() + { + if (self::$instanceNameTemplate == null) { + self::$instanceNameTemplate = new PathTemplate('projects/{project}/instances/{instance}'); + } + + return self::$instanceNameTemplate; + } + + private static function getTableNameTemplate() + { + if (self::$tableNameTemplate == null) { + self::$tableNameTemplate = new PathTemplate('projects/{project}/instances/{instance}/tables/{table}'); + } + + return self::$tableNameTemplate; + } + + private static function getPathTemplateMap() + { + if (self::$pathTemplateMap == null) { + self::$pathTemplateMap = [ + 'instance' => self::getInstanceNameTemplate(), + 'table' => self::getTableNameTemplate(), + ]; + } + + return self::$pathTemplateMap; + } + + private static function getPageStreamingDescriptors() + { + $listTablesPageStreamingDescriptor = + new PageStreamingDescriptor([ + 'requestPageTokenGetMethod' => 'getPageToken', + 'requestPageTokenSetMethod' => 'setPageToken', + 'responsePageTokenGetMethod' => 'getNextPageToken', + 'resourcesGetMethod' => 'getTables', + ]); + + $pageStreamingDescriptors = [ + 'listTables' => $listTablesPageStreamingDescriptor, + ]; + + return $pageStreamingDescriptors; + } + + private static function getGapicVersion() + { + if (!self::$gapicVersionLoaded) { + if (file_exists(__DIR__.'/../VERSION')) { + self::$gapicVersion = trim(file_get_contents(__DIR__.'/../VERSION')); + } elseif (class_exists(Version::class)) { + self::$gapicVersion = Version::VERSION; + } + self::$gapicVersionLoaded = true; + } + + return self::$gapicVersion; + } + + /** + * Formats a string containing the fully-qualified path to represent + * a instance resource. + * + * @param string $project + * @param string $instance + * + * @return string The formatted instance resource. + * @experimental + */ + public static function instanceName($project, $instance) + { + return self::getInstanceNameTemplate()->render([ + 'project' => $project, + 'instance' => $instance, + ]); + } + + /** + * Formats a string containing the fully-qualified path to represent + * a table resource. + * + * @param string $project + * @param string $instance + * @param string $table + * + * @return string The formatted table resource. + * @experimental + */ + public static function tableName($project, $instance, $table) + { + return self::getTableNameTemplate()->render([ + 'project' => $project, + 'instance' => $instance, + 'table' => $table, + ]); + } + + /** + * Parses a formatted name string and returns an associative array of the components in the name. + * The following name formats are supported: + * Template: Pattern + * - instance: projects/{project}/instances/{instance} + * - table: projects/{project}/instances/{instance}/tables/{table}. + * + * The optional $template argument can be supplied to specify a particular pattern, and must + * match one of the templates listed above. If no $template argument is provided, or if the + * $template argument does not match one of the templates listed, then parseName will check + * each of the supported templates, and return the first match. + * + * @param string $formattedName The formatted name string + * @param string $template Optional name of template to match + * + * @return array An associative array from name component IDs to component values. + * + * @throws ValidationException If $formattedName could not be matched. + * @experimental + */ + public static function parseName($formattedName, $template = null) + { + $templateMap = self::getPathTemplateMap(); + + if ($template) { + if (!isset($templateMap[$template])) { + throw new ValidationException("Template name $template does not exist"); + } + + return $templateMap[$template]->match($formattedName); + } + + foreach ($templateMap as $templateName => $pathTemplate) { + try { + return $pathTemplate->match($formattedName); + } catch (ValidationException $ex) { + // Swallow the exception to continue trying other path templates + } + } + throw new ValidationException("Input did not match any known format. Input: $formattedName"); + } + + /** + * Constructor. + * + * @param array $options { + * Optional. Options for configuring the service API wrapper. + * + * @type string $serviceAddress The domain name of the API remote host. + * Default 'bigtableadmin.googleapis.com'. + * @type mixed $port The port on which to connect to the remote host. Default 443. + * @type \Grpc\Channel $channel + * A `Channel` object to be used by gRPC. If not specified, a channel will be constructed. + * @type \Grpc\ChannelCredentials $sslCreds + * A `ChannelCredentials` object for use with an SSL-enabled channel. + * Default: a credentials object returned from + * \Grpc\ChannelCredentials::createSsl() + * NOTE: if the $channel optional argument is specified, then this argument is unused. + * @type bool $forceNewChannel + * If true, this forces gRPC to create a new channel instead of using a persistent channel. + * Defaults to false. + * NOTE: if the $channel optional argument is specified, then this option is unused. + * @type \Google\Auth\CredentialsLoader $credentialsLoader + * A CredentialsLoader object created using the Google\Auth library. + * @type array $scopes A string array of scopes to use when acquiring credentials. + * Defaults to the scopes for the Cloud Bigtable Admin API. + * @type string $clientConfigPath + * Path to a JSON file containing client method configuration, including retry settings. + * Specify this setting to specify the retry behavior of all methods on the client. + * By default this settings points to the default client config file, which is provided + * in the resources folder. The retry settings provided in this option can be overridden + * by settings in $retryingOverride + * @type array $retryingOverride + * An associative array in which the keys are method names (e.g. 'createFoo'), and + * the values are retry settings to use for that method. The retry settings for each + * method can be a {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on {@see Google\GAX\RetrySettings} + * for example usage. Passing a value of null is equivalent to a value of + * ['retriesEnabled' => false]. Retry settings provided in this setting override the + * settings in $clientConfigPath. + * } + * @experimental + */ + public function __construct($options = []) + { + $defaultOptions = [ + 'serviceAddress' => self::SERVICE_ADDRESS, + 'port' => self::DEFAULT_SERVICE_PORT, + 'scopes' => [ + 'https://www.googleapis.com/auth/bigtable.admin', + 'https://www.googleapis.com/auth/bigtable.admin.cluster', + 'https://www.googleapis.com/auth/bigtable.admin.instance', + 'https://www.googleapis.com/auth/bigtable.admin.table', + 'https://www.googleapis.com/auth/cloud-bigtable.admin', + 'https://www.googleapis.com/auth/cloud-bigtable.admin.cluster', + 'https://www.googleapis.com/auth/cloud-bigtable.admin.table', + 'https://www.googleapis.com/auth/cloud-platform', + 'https://www.googleapis.com/auth/cloud-platform.read-only', + ], + 'retryingOverride' => null, + 'libName' => null, + 'libVersion' => null, + 'clientConfigPath' => __DIR__.'/../resources/bigtable_table_admin_client_config.json', + ]; + $options = array_merge($defaultOptions, $options); + + $gapicVersion = $options['libVersion'] ?: self::getGapicVersion(); + + $headerDescriptor = new AgentHeaderDescriptor([ + 'libName' => $options['libName'], + 'libVersion' => $options['libVersion'], + 'gapicVersion' => $gapicVersion, + ]); + + $defaultDescriptors = ['headerDescriptor' => $headerDescriptor]; + $this->descriptors = [ + 'createTable' => $defaultDescriptors, + 'listTables' => $defaultDescriptors, + 'getTable' => $defaultDescriptors, + 'deleteTable' => $defaultDescriptors, + 'modifyColumnFamilies' => $defaultDescriptors, + 'dropRowRange' => $defaultDescriptors, + ]; + $pageStreamingDescriptors = self::getPageStreamingDescriptors(); + foreach ($pageStreamingDescriptors as $method => $pageStreamingDescriptor) { + $this->descriptors[$method]['pageStreamingDescriptor'] = $pageStreamingDescriptor; + } + + $clientConfigJsonString = file_get_contents($options['clientConfigPath']); + $clientConfig = json_decode($clientConfigJsonString, true); + $this->defaultCallSettings = + CallSettings::load( + 'google.bigtable.admin.v2.BigtableTableAdmin', + $clientConfig, + $options['retryingOverride'] + ); + + $this->scopes = $options['scopes']; + + $createStubOptions = []; + if (array_key_exists('sslCreds', $options)) { + $createStubOptions['sslCreds'] = $options['sslCreds']; + } + $this->grpcCredentialsHelper = new GrpcCredentialsHelper($options); + + $createBigtableTableAdminStubFunction = function ($hostname, $opts, $channel) { + return new BigtableTableAdminGrpcClient($hostname, $opts, $channel); + }; + if (array_key_exists('createBigtableTableAdminStubFunction', $options)) { + $createBigtableTableAdminStubFunction = $options['createBigtableTableAdminStubFunction']; + } + $this->bigtableTableAdminStub = $this->grpcCredentialsHelper->createStub($createBigtableTableAdminStubFunction); + } + + /** + * Creates a new table in the specified instance. + * The table can be created with a full set of initial column families, + * specified in the request. + * + * Sample code: + * ``` + * try { + * $bigtableTableAdminClient = new BigtableTableAdminClient(); + * $formattedParent = $bigtableTableAdminClient->instanceName('[PROJECT]', '[INSTANCE]'); + * $tableId = ''; + * $table = new Table(); + * $response = $bigtableTableAdminClient->createTable($formattedParent, $tableId, $table); + * } finally { + * $bigtableTableAdminClient->close(); + * } + * ``` + * + * @param string $parent The unique name of the instance in which to create the table. + * Values are of the form `projects//instances/`. + * @param string $tableId The name by which the new table should be referred to within the parent + * instance, e.g., `foobar` rather than `/tables/foobar`. + * @param Table $table The Table to create. + * @param array $optionalArgs { + * Optional. + * + * @type Split[] $initialSplits + * The optional list of row keys that will be used to initially split the + * table into several tablets (tablets are similar to HBase regions). + * Given two split keys, `s1` and `s2`, three tablets will be created, + * spanning the key ranges: `[, s1), [s1, s2), [s2, )`. + * + * Example: + * + * * Row keys := `["a", "apple", "custom", "customer_1", "customer_2",` + * `"other", "zz"]` + * * initial_split_keys := `["apple", "customer_1", "customer_2", "other"]` + * * Key assignment: + * - Tablet 1 `[, apple) => {"a"}.` + * - Tablet 2 `[apple, customer_1) => {"apple", "custom"}.` + * - Tablet 3 `[customer_1, customer_2) => {"customer_1"}.` + * - Tablet 4 `[customer_2, other) => {"customer_2"}.` + * - Tablet 5 `[other, ) => {"other", "zz"}.` + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\Bigtable\Admin\V2\Table + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function createTable($parent, $tableId, $table, $optionalArgs = []) + { + $request = new CreateTableRequest(); + $request->setParent($parent); + $request->setTableId($tableId); + $request->setTable($table); + if (isset($optionalArgs['initialSplits'])) { + $request->setInitialSplits($optionalArgs['initialSplits']); + } + + $defaultCallSettings = $this->defaultCallSettings['createTable']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableTableAdminStub, + 'CreateTable', + $mergedSettings, + $this->descriptors['createTable'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Lists all tables served from a specified instance. + * + * Sample code: + * ``` + * try { + * $bigtableTableAdminClient = new BigtableTableAdminClient(); + * $formattedParent = $bigtableTableAdminClient->instanceName('[PROJECT]', '[INSTANCE]'); + * // Iterate through all elements + * $pagedResponse = $bigtableTableAdminClient->listTables($formattedParent); + * foreach ($pagedResponse->iterateAllElements() as $element) { + * // doSomethingWith($element); + * } + * + * // OR iterate over pages of elements + * $pagedResponse = $bigtableTableAdminClient->listTables($formattedParent); + * foreach ($pagedResponse->iteratePages() as $page) { + * foreach ($page as $element) { + * // doSomethingWith($element); + * } + * } + * } finally { + * $bigtableTableAdminClient->close(); + * } + * ``` + * + * @param string $parent The unique name of the instance for which tables should be listed. + * Values are of the form `projects//instances/`. + * @param array $optionalArgs { + * Optional. + * + * @type int $view + * The view to be applied to the returned tables' fields. + * Defaults to `NAME_ONLY` if unspecified; no others are currently supported. + * For allowed values, use constants defined on {@see \Google\Bigtable\Admin\V2\Table_View} + * @type string $pageToken + * A page token is used to specify a page of values to be returned. + * If no page token is specified (the default), the first page + * of values will be returned. Any page token used here must have + * been generated by a previous call to the API. + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\GAX\PagedListResponse + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function listTables($parent, $optionalArgs = []) + { + $request = new ListTablesRequest(); + $request->setParent($parent); + if (isset($optionalArgs['view'])) { + $request->setView($optionalArgs['view']); + } + if (isset($optionalArgs['pageToken'])) { + $request->setPageToken($optionalArgs['pageToken']); + } + + $defaultCallSettings = $this->defaultCallSettings['listTables']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableTableAdminStub, + 'ListTables', + $mergedSettings, + $this->descriptors['listTables'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Gets metadata information about the specified table. + * + * Sample code: + * ``` + * try { + * $bigtableTableAdminClient = new BigtableTableAdminClient(); + * $formattedName = $bigtableTableAdminClient->tableName('[PROJECT]', '[INSTANCE]', '[TABLE]'); + * $response = $bigtableTableAdminClient->getTable($formattedName); + * } finally { + * $bigtableTableAdminClient->close(); + * } + * ``` + * + * @param string $name The unique name of the requested table. + * Values are of the form + * `projects//instances//tables/`. + * @param array $optionalArgs { + * Optional. + * + * @type int $view + * The view to be applied to the returned table's fields. + * Defaults to `SCHEMA_VIEW` if unspecified. + * For allowed values, use constants defined on {@see \Google\Bigtable\Admin\V2\Table_View} + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\Bigtable\Admin\V2\Table + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function getTable($name, $optionalArgs = []) + { + $request = new GetTableRequest(); + $request->setName($name); + if (isset($optionalArgs['view'])) { + $request->setView($optionalArgs['view']); + } + + $defaultCallSettings = $this->defaultCallSettings['getTable']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableTableAdminStub, + 'GetTable', + $mergedSettings, + $this->descriptors['getTable'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Permanently deletes a specified table and all of its data. + * + * Sample code: + * ``` + * try { + * $bigtableTableAdminClient = new BigtableTableAdminClient(); + * $formattedName = $bigtableTableAdminClient->tableName('[PROJECT]', '[INSTANCE]', '[TABLE]'); + * $bigtableTableAdminClient->deleteTable($formattedName); + * } finally { + * $bigtableTableAdminClient->close(); + * } + * ``` + * + * @param string $name The unique name of the table to be deleted. + * Values are of the form + * `projects//instances//tables/
`. + * @param array $optionalArgs { + * Optional. + * + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function deleteTable($name, $optionalArgs = []) + { + $request = new DeleteTableRequest(); + $request->setName($name); + + $defaultCallSettings = $this->defaultCallSettings['deleteTable']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableTableAdminStub, + 'DeleteTable', + $mergedSettings, + $this->descriptors['deleteTable'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Performs a series of column family modifications on the specified table. + * Either all or none of the modifications will occur before this method + * returns, but data requests received prior to that point may see a table + * where only some modifications have taken effect. + * + * Sample code: + * ``` + * try { + * $bigtableTableAdminClient = new BigtableTableAdminClient(); + * $formattedName = $bigtableTableAdminClient->tableName('[PROJECT]', '[INSTANCE]', '[TABLE]'); + * $modifications = []; + * $response = $bigtableTableAdminClient->modifyColumnFamilies($formattedName, $modifications); + * } finally { + * $bigtableTableAdminClient->close(); + * } + * ``` + * + * @param string $name The unique name of the table whose families should be modified. + * Values are of the form + * `projects//instances//tables/
`. + * @param Modification[] $modifications Modifications to be atomically applied to the specified table's families. + * Entries are applied in order, meaning that earlier modifications can be + * masked by later ones (in the case of repeated updates to the same family, + * for example). + * @param array $optionalArgs { + * Optional. + * + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\Bigtable\Admin\V2\Table + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function modifyColumnFamilies($name, $modifications, $optionalArgs = []) + { + $request = new ModifyColumnFamiliesRequest(); + $request->setName($name); + $request->setModifications($modifications); + + $defaultCallSettings = $this->defaultCallSettings['modifyColumnFamilies']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableTableAdminStub, + 'ModifyColumnFamilies', + $mergedSettings, + $this->descriptors['modifyColumnFamilies'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Permanently drop/delete a row range from a specified table. The request can + * specify whether to delete all rows in a table, or only those that match a + * particular prefix. + * + * Sample code: + * ``` + * try { + * $bigtableTableAdminClient = new BigtableTableAdminClient(); + * $formattedName = $bigtableTableAdminClient->tableName('[PROJECT]', '[INSTANCE]', '[TABLE]'); + * $bigtableTableAdminClient->dropRowRange($formattedName); + * } finally { + * $bigtableTableAdminClient->close(); + * } + * ``` + * + * @param string $name The unique name of the table on which to drop a range of rows. + * Values are of the form + * `projects//instances//tables/
`. + * @param array $optionalArgs { + * Optional. + * + * @type string $rowKeyPrefix + * Delete all rows that start with this row key prefix. Prefix cannot be + * zero length. + * @type bool $deleteAllDataFromTable + * Delete all rows in the table. Setting this to false is a no-op. + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function dropRowRange($name, $optionalArgs = []) + { + $request = new DropRowRangeRequest(); + $request->setName($name); + if (isset($optionalArgs['rowKeyPrefix'])) { + $request->setRowKeyPrefix($optionalArgs['rowKeyPrefix']); + } + if (isset($optionalArgs['deleteAllDataFromTable'])) { + $request->setDeleteAllDataFromTable($optionalArgs['deleteAllDataFromTable']); + } + + $defaultCallSettings = $this->defaultCallSettings['dropRowRange']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableTableAdminStub, + 'DropRowRange', + $mergedSettings, + $this->descriptors['dropRowRange'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Initiates an orderly shutdown in which preexisting calls continue but new + * calls are immediately cancelled. + * + * @experimental + */ + public function close() + { + $this->bigtableTableAdminStub->close(); + } + + private function createCredentialsCallback() + { + return $this->grpcCredentialsHelper->createCallCredentialsCallback(); + } +} diff --git a/src/Bigtable/Admin/V2/resources/bigtable_instance_admin_client_config.json b/src/Bigtable/Admin/V2/resources/bigtable_instance_admin_client_config.json new file mode 100644 index 000000000000..ee9e46f78be5 --- /dev/null +++ b/src/Bigtable/Admin/V2/resources/bigtable_instance_admin_client_config.json @@ -0,0 +1,78 @@ +{ + "interfaces": { + "google.bigtable.admin.v2.BigtableInstanceAdmin": { + "retry_codes": { + "idempotent": [ + "DEADLINE_EXCEEDED", + "UNAVAILABLE" + ], + "non_idempotent": [ + "UNAVAILABLE" + ] + }, + "retry_params": { + "default": { + "initial_retry_delay_millis": 5, + "retry_delay_multiplier": 2.0, + "max_retry_delay_millis": 60000, + "initial_rpc_timeout_millis": 60000, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 60000, + "total_timeout_millis": 600000 + } + }, + "methods": { + "CreateInstance": { + "timeout_millis": 60000, + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + }, + "GetInstance": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default" + }, + "ListInstances": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default" + }, + "UpdateInstance": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default" + }, + "DeleteInstance": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default" + }, + "CreateCluster": { + "timeout_millis": 60000, + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + }, + "GetCluster": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default" + }, + "ListClusters": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default" + }, + "UpdateCluster": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default" + }, + "DeleteCluster": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default" + } + } + } + } +} diff --git a/src/Bigtable/Admin/V2/resources/bigtable_table_admin_client_config.json b/src/Bigtable/Admin/V2/resources/bigtable_table_admin_client_config.json new file mode 100644 index 000000000000..ef22010c1bf4 --- /dev/null +++ b/src/Bigtable/Admin/V2/resources/bigtable_table_admin_client_config.json @@ -0,0 +1,56 @@ +{ + "interfaces": { + "google.bigtable.admin.v2.BigtableTableAdmin": { + "retry_codes": { + "idempotent": [ + "DEADLINE_EXCEEDED", + "UNAVAILABLE" + ], + "non_idempotent": [] + }, + "retry_params": { + "default": { + "initial_retry_delay_millis": 100, + "retry_delay_multiplier": 1.3, + "max_retry_delay_millis": 60000, + "initial_rpc_timeout_millis": 20000, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 20000, + "total_timeout_millis": 600000 + } + }, + "methods": { + "CreateTable": { + "timeout_millis": 130000, + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + }, + "ListTables": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default" + }, + "GetTable": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default" + }, + "DeleteTable": { + "timeout_millis": 60000, + "retry_codes_name": "idempotent", + "retry_params_name": "default" + }, + "ModifyColumnFamilies": { + "timeout_millis": 60000, + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + }, + "DropRowRange": { + "timeout_millis": 60000, + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + } + } + } + } +} diff --git a/src/Bigtable/LICENSE b/src/Bigtable/LICENSE new file mode 100644 index 000000000000..8f71f43fee3f --- /dev/null +++ b/src/Bigtable/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/src/Bigtable/README.md b/src/Bigtable/README.md new file mode 100644 index 000000000000..21088eddab7b --- /dev/null +++ b/src/Bigtable/README.md @@ -0,0 +1,16 @@ +# Google Cloud PHP Bigtable + +> Idiomatic PHP client for [Bigtable](https://cloud.google.com/bigtable/). + +* [Homepage](http://googlecloudplatform.github.io/google-cloud-php) +* [API documentation](http://googlecloudplatform.github.io/google-cloud-php/#/docs/cloud-bigtable/latest/bigtable/bigtableclient) + +**NOTE:** This repository is part of [Google Cloud PHP](https://github.com/googlecloudplatform/google-cloud-php). Any +support requests, bug reports, or development contributions should be directed to +that project. + +## Installation + +``` +$ composer require google/cloud-bigtable +``` diff --git a/src/Bigtable/V2/BigtableClient.php b/src/Bigtable/V2/BigtableClient.php new file mode 100644 index 000000000000..369e5a1c6ba7 --- /dev/null +++ b/src/Bigtable/V2/BigtableClient.php @@ -0,0 +1,41 @@ +tableName('[PROJECT]', '[INSTANCE]', '[TABLE]'); + * // Read all responses until the stream is complete + * $stream = $bigtableClient->readRows($formattedTableName); + * foreach ($stream->readAll() as $element) { + * // doSomethingWith($element); + * } + * } finally { + * $bigtableClient->close(); + * } + * ``` + * + * Many parameters require resource names to be formatted in a particular way. To assist + * with these names, this class includes a format method for each type of name, and additionally + * a parseName method to extract the individual identifiers contained within formatted names + * that are returned by the API. + * + * @experimental + */ +class BigtableGapicClient +{ + /** + * The default address of the service. + */ + const SERVICE_ADDRESS = 'bigtable.googleapis.com'; + + /** + * The default port of the service. + */ + const DEFAULT_SERVICE_PORT = 443; + + /** + * The name of the code generator, to be included in the agent header. + */ + const CODEGEN_NAME = 'gapic'; + + /** + * The code generator version, to be included in the agent header. + */ + const CODEGEN_VERSION = '0.0.5'; + + private static $tableNameTemplate; + private static $pathTemplateMap; + private static $gapicVersion; + private static $gapicVersionLoaded = false; + + protected $grpcCredentialsHelper; + protected $bigtableStub; + private $scopes; + private $defaultCallSettings; + private $descriptors; + + private static function getTableNameTemplate() + { + if (self::$tableNameTemplate == null) { + self::$tableNameTemplate = new PathTemplate('projects/{project}/instances/{instance}/tables/{table}'); + } + + return self::$tableNameTemplate; + } + + private static function getPathTemplateMap() + { + if (self::$pathTemplateMap == null) { + self::$pathTemplateMap = [ + 'table' => self::getTableNameTemplate(), + ]; + } + + return self::$pathTemplateMap; + } + + private static function getGrpcStreamingDescriptors() + { + return [ + 'readRows' => [ + 'grpcStreamingType' => 'ServerStreaming', + ], + 'sampleRowKeys' => [ + 'grpcStreamingType' => 'ServerStreaming', + ], + 'mutateRows' => [ + 'grpcStreamingType' => 'ServerStreaming', + ], + ]; + } + + private static function getGapicVersion() + { + if (!self::$gapicVersionLoaded) { + if (file_exists(__DIR__.'/../VERSION')) { + self::$gapicVersion = trim(file_get_contents(__DIR__.'/../VERSION')); + } elseif (class_exists(Version::class)) { + self::$gapicVersion = Version::VERSION; + } + self::$gapicVersionLoaded = true; + } + + return self::$gapicVersion; + } + + /** + * Formats a string containing the fully-qualified path to represent + * a table resource. + * + * @param string $project + * @param string $instance + * @param string $table + * + * @return string The formatted table resource. + * @experimental + */ + public static function tableName($project, $instance, $table) + { + return self::getTableNameTemplate()->render([ + 'project' => $project, + 'instance' => $instance, + 'table' => $table, + ]); + } + + /** + * Parses a formatted name string and returns an associative array of the components in the name. + * The following name formats are supported: + * Template: Pattern + * - table: projects/{project}/instances/{instance}/tables/{table}. + * + * The optional $template argument can be supplied to specify a particular pattern, and must + * match one of the templates listed above. If no $template argument is provided, or if the + * $template argument does not match one of the templates listed, then parseName will check + * each of the supported templates, and return the first match. + * + * @param string $formattedName The formatted name string + * @param string $template Optional name of template to match + * + * @return array An associative array from name component IDs to component values. + * + * @throws ValidationException If $formattedName could not be matched. + * @experimental + */ + public static function parseName($formattedName, $template = null) + { + $templateMap = self::getPathTemplateMap(); + + if ($template) { + if (!isset($templateMap[$template])) { + throw new ValidationException("Template name $template does not exist"); + } + + return $templateMap[$template]->match($formattedName); + } + + foreach ($templateMap as $templateName => $pathTemplate) { + try { + return $pathTemplate->match($formattedName); + } catch (ValidationException $ex) { + // Swallow the exception to continue trying other path templates + } + } + throw new ValidationException("Input did not match any known format. Input: $formattedName"); + } + + /** + * Constructor. + * + * @param array $options { + * Optional. Options for configuring the service API wrapper. + * + * @type string $serviceAddress The domain name of the API remote host. + * Default 'bigtable.googleapis.com'. + * @type mixed $port The port on which to connect to the remote host. Default 443. + * @type \Grpc\Channel $channel + * A `Channel` object to be used by gRPC. If not specified, a channel will be constructed. + * @type \Grpc\ChannelCredentials $sslCreds + * A `ChannelCredentials` object for use with an SSL-enabled channel. + * Default: a credentials object returned from + * \Grpc\ChannelCredentials::createSsl() + * NOTE: if the $channel optional argument is specified, then this argument is unused. + * @type bool $forceNewChannel + * If true, this forces gRPC to create a new channel instead of using a persistent channel. + * Defaults to false. + * NOTE: if the $channel optional argument is specified, then this option is unused. + * @type \Google\Auth\CredentialsLoader $credentialsLoader + * A CredentialsLoader object created using the Google\Auth library. + * @type array $scopes A string array of scopes to use when acquiring credentials. + * Defaults to the scopes for the Google Cloud Bigtable API. + * @type string $clientConfigPath + * Path to a JSON file containing client method configuration, including retry settings. + * Specify this setting to specify the retry behavior of all methods on the client. + * By default this settings points to the default client config file, which is provided + * in the resources folder. The retry settings provided in this option can be overridden + * by settings in $retryingOverride + * @type array $retryingOverride + * An associative array in which the keys are method names (e.g. 'createFoo'), and + * the values are retry settings to use for that method. The retry settings for each + * method can be a {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on {@see Google\GAX\RetrySettings} + * for example usage. Passing a value of null is equivalent to a value of + * ['retriesEnabled' => false]. Retry settings provided in this setting override the + * settings in $clientConfigPath. + * } + * @experimental + */ + public function __construct($options = []) + { + $defaultOptions = [ + 'serviceAddress' => self::SERVICE_ADDRESS, + 'port' => self::DEFAULT_SERVICE_PORT, + 'scopes' => [ + 'https://www.googleapis.com/auth/bigtable.data', + 'https://www.googleapis.com/auth/bigtable.data.readonly', + 'https://www.googleapis.com/auth/cloud-bigtable.data', + 'https://www.googleapis.com/auth/cloud-bigtable.data.readonly', + 'https://www.googleapis.com/auth/cloud-platform', + 'https://www.googleapis.com/auth/cloud-platform.read-only', + ], + 'retryingOverride' => null, + 'libName' => null, + 'libVersion' => null, + 'clientConfigPath' => __DIR__.'/../resources/bigtable_client_config.json', + ]; + $options = array_merge($defaultOptions, $options); + + $gapicVersion = $options['libVersion'] ?: self::getGapicVersion(); + + $headerDescriptor = new AgentHeaderDescriptor([ + 'libName' => $options['libName'], + 'libVersion' => $options['libVersion'], + 'gapicVersion' => $gapicVersion, + ]); + + $defaultDescriptors = ['headerDescriptor' => $headerDescriptor]; + $this->descriptors = [ + 'readRows' => $defaultDescriptors, + 'sampleRowKeys' => $defaultDescriptors, + 'mutateRow' => $defaultDescriptors, + 'mutateRows' => $defaultDescriptors, + 'checkAndMutateRow' => $defaultDescriptors, + 'readModifyWriteRow' => $defaultDescriptors, + ]; + $grpcStreamingDescriptors = self::getGrpcStreamingDescriptors(); + foreach ($grpcStreamingDescriptors as $method => $grpcStreamingDescriptor) { + $this->descriptors[$method]['grpcStreamingDescriptor'] = $grpcStreamingDescriptor; + } + + $clientConfigJsonString = file_get_contents($options['clientConfigPath']); + $clientConfig = json_decode($clientConfigJsonString, true); + $this->defaultCallSettings = + CallSettings::load( + 'google.bigtable.v2.Bigtable', + $clientConfig, + $options['retryingOverride'] + ); + + $this->scopes = $options['scopes']; + + $createStubOptions = []; + if (array_key_exists('sslCreds', $options)) { + $createStubOptions['sslCreds'] = $options['sslCreds']; + } + $this->grpcCredentialsHelper = new GrpcCredentialsHelper($options); + + $createBigtableStubFunction = function ($hostname, $opts, $channel) { + return new BigtableGrpcClient($hostname, $opts, $channel); + }; + if (array_key_exists('createBigtableStubFunction', $options)) { + $createBigtableStubFunction = $options['createBigtableStubFunction']; + } + $this->bigtableStub = $this->grpcCredentialsHelper->createStub($createBigtableStubFunction); + } + + /** + * Streams back the contents of all requested rows in key order, optionally + * applying the same Reader filter to each. Depending on their size, + * rows and cells may be broken up across multiple responses, but + * atomicity of each row will still be preserved. See the + * ReadRowsResponse documentation for details. + * + * Sample code: + * ``` + * try { + * $bigtableClient = new BigtableClient(); + * $formattedTableName = $bigtableClient->tableName('[PROJECT]', '[INSTANCE]', '[TABLE]'); + * // Read all responses until the stream is complete + * $stream = $bigtableClient->readRows($formattedTableName); + * foreach ($stream->readAll() as $element) { + * // doSomethingWith($element); + * } + * } finally { + * $bigtableClient->close(); + * } + * ``` + * + * @param string $tableName The unique name of the table from which to read. + * Values are of the form + * `projects//instances//tables/
`. + * @param array $optionalArgs { + * Optional. + * + * @type RowSet $rows + * The row keys and/or ranges to read. If not specified, reads from all rows. + * @type RowFilter $filter + * The filter to apply to the contents of the specified row(s). If unset, + * reads the entirety of each row. + * @type int $rowsLimit + * The read will terminate after committing to N rows' worth of results. The + * default (zero) is to return all results. + * @type int $timeoutMillis + * Timeout to use for this call. + * } + * + * @return \Google\GAX\ServerStream + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function readRows($tableName, $optionalArgs = []) + { + $request = new ReadRowsRequest(); + $request->setTableName($tableName); + if (isset($optionalArgs['rows'])) { + $request->setRows($optionalArgs['rows']); + } + if (isset($optionalArgs['filter'])) { + $request->setFilter($optionalArgs['filter']); + } + if (isset($optionalArgs['rowsLimit'])) { + $request->setRowsLimit($optionalArgs['rowsLimit']); + } + + if (array_key_exists('timeoutMillis', $optionalArgs)) { + $optionalArgs['retrySettings'] = [ + 'retriesEnabled' => false, + 'noRetriesRpcTimeoutMillis' => $optionalArgs['timeoutMillis'], + ]; + } + + $defaultCallSettings = $this->defaultCallSettings['readRows']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableStub, + 'ReadRows', + $mergedSettings, + $this->descriptors['readRows'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Returns a sample of row keys in the table. The returned row keys will + * delimit contiguous sections of the table of approximately equal size, + * which can be used to break up the data for distributed tasks like + * mapreduces. + * + * Sample code: + * ``` + * try { + * $bigtableClient = new BigtableClient(); + * $formattedTableName = $bigtableClient->tableName('[PROJECT]', '[INSTANCE]', '[TABLE]'); + * // Read all responses until the stream is complete + * $stream = $bigtableClient->sampleRowKeys($formattedTableName); + * foreach ($stream->readAll() as $element) { + * // doSomethingWith($element); + * } + * } finally { + * $bigtableClient->close(); + * } + * ``` + * + * @param string $tableName The unique name of the table from which to sample row keys. + * Values are of the form + * `projects//instances//tables/
`. + * @param array $optionalArgs { + * Optional. + * + * @type int $timeoutMillis + * Timeout to use for this call. + * } + * + * @return \Google\GAX\ServerStream + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function sampleRowKeys($tableName, $optionalArgs = []) + { + $request = new SampleRowKeysRequest(); + $request->setTableName($tableName); + + if (array_key_exists('timeoutMillis', $optionalArgs)) { + $optionalArgs['retrySettings'] = [ + 'retriesEnabled' => false, + 'noRetriesRpcTimeoutMillis' => $optionalArgs['timeoutMillis'], + ]; + } + + $defaultCallSettings = $this->defaultCallSettings['sampleRowKeys']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableStub, + 'SampleRowKeys', + $mergedSettings, + $this->descriptors['sampleRowKeys'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Mutates a row atomically. Cells already present in the row are left + * unchanged unless explicitly changed by `mutation`. + * + * Sample code: + * ``` + * try { + * $bigtableClient = new BigtableClient(); + * $formattedTableName = $bigtableClient->tableName('[PROJECT]', '[INSTANCE]', '[TABLE]'); + * $rowKey = ''; + * $mutations = []; + * $response = $bigtableClient->mutateRow($formattedTableName, $rowKey, $mutations); + * } finally { + * $bigtableClient->close(); + * } + * ``` + * + * @param string $tableName The unique name of the table to which the mutation should be applied. + * Values are of the form + * `projects//instances//tables/
`. + * @param string $rowKey The key of the row to which the mutation should be applied. + * @param Mutation[] $mutations Changes to be atomically applied to the specified row. Entries are applied + * in order, meaning that earlier mutations can be masked by later ones. + * Must contain at least one entry and at most 100000. + * @param array $optionalArgs { + * Optional. + * + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\Bigtable\V2\MutateRowResponse + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function mutateRow($tableName, $rowKey, $mutations, $optionalArgs = []) + { + $request = new MutateRowRequest(); + $request->setTableName($tableName); + $request->setRowKey($rowKey); + $request->setMutations($mutations); + + $defaultCallSettings = $this->defaultCallSettings['mutateRow']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableStub, + 'MutateRow', + $mergedSettings, + $this->descriptors['mutateRow'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Mutates multiple rows in a batch. Each individual row is mutated + * atomically as in MutateRow, but the entire batch is not executed + * atomically. + * + * Sample code: + * ``` + * try { + * $bigtableClient = new BigtableClient(); + * $formattedTableName = $bigtableClient->tableName('[PROJECT]', '[INSTANCE]', '[TABLE]'); + * $entries = []; + * // Read all responses until the stream is complete + * $stream = $bigtableClient->mutateRows($formattedTableName, $entries); + * foreach ($stream->readAll() as $element) { + * // doSomethingWith($element); + * } + * } finally { + * $bigtableClient->close(); + * } + * ``` + * + * @param string $tableName The unique name of the table to which the mutations should be applied. + * @param Entry[] $entries The row keys and corresponding mutations to be applied in bulk. + * Each entry is applied as an atomic mutation, but the entries may be + * applied in arbitrary order (even between entries for the same row). + * At least one entry must be specified, and in total the entries can + * contain at most 100000 mutations. + * @param array $optionalArgs { + * Optional. + * + * @type int $timeoutMillis + * Timeout to use for this call. + * } + * + * @return \Google\GAX\ServerStream + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function mutateRows($tableName, $entries, $optionalArgs = []) + { + $request = new MutateRowsRequest(); + $request->setTableName($tableName); + $request->setEntries($entries); + + if (array_key_exists('timeoutMillis', $optionalArgs)) { + $optionalArgs['retrySettings'] = [ + 'retriesEnabled' => false, + 'noRetriesRpcTimeoutMillis' => $optionalArgs['timeoutMillis'], + ]; + } + + $defaultCallSettings = $this->defaultCallSettings['mutateRows']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableStub, + 'MutateRows', + $mergedSettings, + $this->descriptors['mutateRows'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Mutates a row atomically based on the output of a predicate Reader filter. + * + * Sample code: + * ``` + * try { + * $bigtableClient = new BigtableClient(); + * $formattedTableName = $bigtableClient->tableName('[PROJECT]', '[INSTANCE]', '[TABLE]'); + * $rowKey = ''; + * $response = $bigtableClient->checkAndMutateRow($formattedTableName, $rowKey); + * } finally { + * $bigtableClient->close(); + * } + * ``` + * + * @param string $tableName The unique name of the table to which the conditional mutation should be + * applied. + * Values are of the form + * `projects//instances//tables/
`. + * @param string $rowKey The key of the row to which the conditional mutation should be applied. + * @param array $optionalArgs { + * Optional. + * + * @type RowFilter $predicateFilter + * The filter to be applied to the contents of the specified row. Depending + * on whether or not any results are yielded, either `true_mutations` or + * `false_mutations` will be executed. If unset, checks that the row contains + * any values at all. + * @type Mutation[] $trueMutations + * Changes to be atomically applied to the specified row if `predicate_filter` + * yields at least one cell when applied to `row_key`. Entries are applied in + * order, meaning that earlier mutations can be masked by later ones. + * Must contain at least one entry if `false_mutations` is empty, and at most + * 100000. + * @type Mutation[] $falseMutations + * Changes to be atomically applied to the specified row if `predicate_filter` + * does not yield any cells when applied to `row_key`. Entries are applied in + * order, meaning that earlier mutations can be masked by later ones. + * Must contain at least one entry if `true_mutations` is empty, and at most + * 100000. + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\Bigtable\V2\CheckAndMutateRowResponse + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function checkAndMutateRow($tableName, $rowKey, $optionalArgs = []) + { + $request = new CheckAndMutateRowRequest(); + $request->setTableName($tableName); + $request->setRowKey($rowKey); + if (isset($optionalArgs['predicateFilter'])) { + $request->setPredicateFilter($optionalArgs['predicateFilter']); + } + if (isset($optionalArgs['trueMutations'])) { + $request->setTrueMutations($optionalArgs['trueMutations']); + } + if (isset($optionalArgs['falseMutations'])) { + $request->setFalseMutations($optionalArgs['falseMutations']); + } + + $defaultCallSettings = $this->defaultCallSettings['checkAndMutateRow']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableStub, + 'CheckAndMutateRow', + $mergedSettings, + $this->descriptors['checkAndMutateRow'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Modifies a row atomically. The method reads the latest existing timestamp + * and value from the specified columns and writes a new entry based on + * pre-defined read/modify/write rules. The new value for the timestamp is the + * greater of the existing timestamp or the current server time. The method + * returns the new contents of all modified cells. + * + * Sample code: + * ``` + * try { + * $bigtableClient = new BigtableClient(); + * $formattedTableName = $bigtableClient->tableName('[PROJECT]', '[INSTANCE]', '[TABLE]'); + * $rowKey = ''; + * $rules = []; + * $response = $bigtableClient->readModifyWriteRow($formattedTableName, $rowKey, $rules); + * } finally { + * $bigtableClient->close(); + * } + * ``` + * + * @param string $tableName The unique name of the table to which the read/modify/write rules should be + * applied. + * Values are of the form + * `projects//instances//tables/
`. + * @param string $rowKey The key of the row to which the read/modify/write rules should be applied. + * @param ReadModifyWriteRule[] $rules Rules specifying how the specified row's contents are to be transformed + * into writes. Entries are applied in order, meaning that earlier rules will + * affect the results of later ones. + * @param array $optionalArgs { + * Optional. + * + * @type \Google\GAX\RetrySettings|array $retrySettings + * Retry settings to use for this call. Can be a + * {@see Google\GAX\RetrySettings} object, or an associative array + * of retry settings parameters. See the documentation on + * {@see Google\GAX\RetrySettings} for example usage. + * } + * + * @return \Google\Bigtable\V2\ReadModifyWriteRowResponse + * + * @throws \Google\GAX\ApiException if the remote call fails + * @experimental + */ + public function readModifyWriteRow($tableName, $rowKey, $rules, $optionalArgs = []) + { + $request = new ReadModifyWriteRowRequest(); + $request->setTableName($tableName); + $request->setRowKey($rowKey); + $request->setRules($rules); + + $defaultCallSettings = $this->defaultCallSettings['readModifyWriteRow']; + if (isset($optionalArgs['retrySettings']) && is_array($optionalArgs['retrySettings'])) { + $optionalArgs['retrySettings'] = $defaultCallSettings->getRetrySettings()->with( + $optionalArgs['retrySettings'] + ); + } + $mergedSettings = $defaultCallSettings->merge(new CallSettings($optionalArgs)); + $callable = ApiCallable::createApiCall( + $this->bigtableStub, + 'ReadModifyWriteRow', + $mergedSettings, + $this->descriptors['readModifyWriteRow'] + ); + + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + + /** + * Initiates an orderly shutdown in which preexisting calls continue but new + * calls are immediately cancelled. + * + * @experimental + */ + public function close() + { + $this->bigtableStub->close(); + } + + private function createCredentialsCallback() + { + return $this->grpcCredentialsHelper->createCallCredentialsCallback(); + } +} diff --git a/src/Bigtable/V2/README.md b/src/Bigtable/V2/README.md new file mode 100644 index 000000000000..21088eddab7b --- /dev/null +++ b/src/Bigtable/V2/README.md @@ -0,0 +1,16 @@ +# Google Cloud PHP Bigtable + +> Idiomatic PHP client for [Bigtable](https://cloud.google.com/bigtable/). + +* [Homepage](http://googlecloudplatform.github.io/google-cloud-php) +* [API documentation](http://googlecloudplatform.github.io/google-cloud-php/#/docs/cloud-bigtable/latest/bigtable/bigtableclient) + +**NOTE:** This repository is part of [Google Cloud PHP](https://github.com/googlecloudplatform/google-cloud-php). Any +support requests, bug reports, or development contributions should be directed to +that project. + +## Installation + +``` +$ composer require google/cloud-bigtable +``` diff --git a/src/Bigtable/V2/resources/bigtable_client_config.json b/src/Bigtable/V2/resources/bigtable_client_config.json new file mode 100644 index 000000000000..a8dcf28e0c4f --- /dev/null +++ b/src/Bigtable/V2/resources/bigtable_client_config.json @@ -0,0 +1,50 @@ +{ + "interfaces": { + "google.bigtable.v2.Bigtable": { + "retry_codes": { + "idempotent": [ + "DEADLINE_EXCEEDED", + "UNAVAILABLE" + ], + "non_idempotent": [] + }, + "retry_params": { + "default": { + "initial_retry_delay_millis": 100, + "retry_delay_multiplier": 1.3, + "max_retry_delay_millis": 60000, + "initial_rpc_timeout_millis": 20000, + "rpc_timeout_multiplier": 1.0, + "max_rpc_timeout_millis": 20000, + "total_timeout_millis": 600000 + } + }, + "methods": { + "ReadRows": { + "timeout_millis": 60000 + }, + "SampleRowKeys": { + "timeout_millis": 60000 + }, + "MutateRow": { + "timeout_millis": 60000, + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + }, + "MutateRows": { + "timeout_millis": 60000 + }, + "CheckAndMutateRow": { + "timeout_millis": 60000, + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + }, + "ReadModifyWriteRow": { + "timeout_millis": 60000, + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + } + } + } + } +} diff --git a/src/Bigtable/VERSION b/src/Bigtable/VERSION new file mode 100644 index 000000000000..6e8bf73aa550 --- /dev/null +++ b/src/Bigtable/VERSION @@ -0,0 +1 @@ +0.1.0 diff --git a/src/Bigtable/composer.json b/src/Bigtable/composer.json new file mode 100644 index 000000000000..99ee346144df --- /dev/null +++ b/src/Bigtable/composer.json @@ -0,0 +1,24 @@ +{ + "name": "google/cloud-bigtable", + "description": "Cloud Bigtable Client for PHP", + "license": "Apache-2.0", + "minimum-stability": "stable", + "require": { + "ext-grpc": "*", + "google/proto-client": "^0.26", + "google/gax": "^0.26" + }, + "extra": { + "component": { + "id": "cloud-bigtable", + "target": "GoogleCloudPlatform/google-cloud-php-bigtable.git", + "path": "src/Bigtable", + "entry": null + } + }, + "autoload": { + "psr-4": { + "Google\\Cloud\\Bigtable\\": "" + } + } +}