blob: e5abc850d4e18c560f85754a7fa58085a0434820 [file] [log] [blame] [view]
[![Dart CI](https://github.com/dart-lang/gcloud/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/gcloud/actions/workflows/test-package.yml)
[![pub package](https://img.shields.io/pub/v/gcloud.svg)](https://pub.dev/packages/gcloud)
[![package publisher](https://img.shields.io/pub/publisher/gcloud.svg)](https://pub.dev/packages/gcloud/publisher)
The `gcloud` package provides a high level idiomatic Dart interface to some of
the most widely used Google Cloud Platform services.
## Google Cloud Platform support package (gcloud)
Currently the following services are supported:
* Cloud Datastore
* Cloud Storage
* Cloud Pub/Sub
## Status: Experimental
**NOTE**: This package is currently experimental and published under the
[labs.dart.dev](https://dart.dev/dart-team-packages) pub publisher in order to
solicit feedback.
For packages in the labs.dart.dev publisher we generally plan to either graduate
the package into a supported publisher (dart.dev, tools.dart.dev) after a period
of feedback and iteration, or discontinue the package. These packages have a
much higher expected rate of API and breaking changes.
Your feedback is valuable and will help us evolve this package. For general
feedback, suggestions, and comments, please file an issue in the
[bug tracker](https://github.com/dart-lang/gcloud/issues).
## API details
The APIs in this package are all based on the generic generated APIs in the
[googleapis] and [googleapis_beta][googleapisbeta] packages.
This means that the authentication model for using the APIs in this package
uses the [googleapis_auth][googleapisauth] package.
Note that this package is only intended for being used with the standalone VM
in a server or command line application. Don't expect this package to work on
the browser or in Flutter.
The code snippets below demonstrating the use of this package all assume that
the following imports are present:
```dart
import 'dart:io';
import 'package:googleapis_auth/auth_io.dart' as auth;
import 'package:http/http.dart' as http;
import 'package:gcloud/db.dart';
import 'package:gcloud/storage.dart';
import 'package:gcloud/pubsub.dart';
import 'package:gcloud/service_scope.dart' as ss;
import 'package:gcloud/datastore.dart' as datastore;
```
### Getting access to the APIs
The first step in using the APIs is to get an authenticated HTTP client and
with that create API class instances for accessing the different APIs. The
code below assumes that you have a Google Cloud Project called `my-project`
with credentials for a service account from that project stored in the file
`my-project.json`.
```dart
// Read the service account credentials from the file.
var jsonCredentials = new File('my-project.json').readAsStringSync();
var credentials = new auth.ServiceAccountCredentials.fromJson(jsonCredentials);
// Get an HTTP authenticated client using the service account credentials.
var scopes = []
..addAll(datastore.Datastore.Scopes)
..addAll(Storage.SCOPES)
..addAll(PubSub.SCOPES);
var client = await auth.clientViaServiceAccount(credentials, scopes);
// Instantiate objects to access Cloud Datastore, Cloud Storage
// and Cloud Pub/Sub APIs.
var db = new DatastoreDB(
new datastore.Datastore(client, 's~my-project'));
var storage = new Storage(client, 'my-project');
var pubsub = new PubSub(client, 'my-project');
```
All the APIs in this package supports the use of 'service scopes'. Service
scopes are described in details below.
```dart
ss.fork(() {
// register the services in the new service scope.
registerDbService(db);
registerStorageService(storage);
registerPubSubService(pubsub);
// Run application using these services.
});
```
The services registered with the service scope can now be reached from within
all the code running in the same service scope using the below getters.
```dart
dbService.
storageService.
pubsubService.
```
This way it is not necessary to pass the service objects around in your code.
### Use with App Engine
The `gcloud` package is also integrated in the Dart [appengine] package. This
means the `gcloud` services are available both via the appengine context and
service scopes. The authentication required to access the Google Cloud Platform
services is handled automatically.
This means that getting to the App Engine Datastore can be through either
the App Engine context
```dart
var db = context.services.db;
```
or just using the service scope registration.
```dart
var db = dbService;
```
## Cloud Datastore
Google Cloud Datastore provide a NoSQL, schemaless database for storing
non-relational data. See the product page
[https://cloud.google.com/datastore/][Datastore] for more information.
The Cloud Datastore API provides a mapping of Dart objects to entities stored
in the Datastore. The following example shows how to annotate a class to
make it possible to store instances of it in the Datastore.
```dart
@db.Kind()
class Person extends db.Model {
@db.StringProperty()
String name;
@db.IntProperty()
int age;
}
```
The `Kind` annotation tell that instances of this class can be stored. The
class must also inherit from `Model`. Now to store an object into the
Datastore create an instance and use the `commit` function.
```dart
var person = new Person()
..name = ''
..age = 42;
await db.commit(inserts: [person]);
```
The function `query` is used to build a `Query` object which can be run to
perform the query.
```dart
var persons = (await db.query<Person>().run()).toList();
```
To fetch one or multiple existing entities, use `lookup`.
```dart
var key = new Person()
..name = 'UniqueName'
..age = 42
..parentKey = db.emptyKey;
var person = (await db.lookup<Person>([key])).single;
var people = await db.lookup<Person>([key1, key2]);
```
NOTE: This package include a lower level API provided through the class
`Datastore` on top of which the `DatastoreDB` API is build. The main reason
for this additional API level is to bridge the gap between the different APIs
exposed inside App Engine and through the public REST API. We reserve the
rights to modify and maybe even remove this additional layer at any time.
## Cloud Storage
Google Cloud Storage provide a highly available object store (aka BLOB
store). See the product page [https://cloud.google.com/storage/][GCS]
for more information.
In Cloud Storage the objects (BLOBs) are organized in _buckets_. Each bucket
has a name in a global namespace. The following code creates a new bucket
named `my-bucket` and writes the content of the file `my-file.txt` to the
object named `my-object`.
```dart
var bucket = await storage.createBucket('my-bucket');
new File('my-file.txt').openRead().pipe(bucket.write('my-object'));
```
The following code will read back the object.
```dart
bucket.read('my-object').pipe(new File('my-file-copy.txt').openWrite());
```
## Cloud Pub/Sub
Google Cloud Pub/Sub provides many-to-many, asynchronous messaging. See the
product page [https://cloud.google.com/pubsub/][PubSub] for more information.
Cloud Pub/Sub uses two concepts for messaging. _Topics_ are used if you want
to send messages and _subscriptions_ are used to subscribe to topics and
receive the messages. This decouples the producer of a message from the
consumer of a message.
The following code creates a _topic_ and sends a simple test message:
```dart
var topic = await pubsub.createTopic('my-topic');
await topic.publishString('Hello, world!')
```
With the following code a _subscription_ is created on the _topic_ and
a message is pulled using the subscription. A received message must be
acknowledged when the consumer has processed it.
```dart
var subscription =
await pubsub.createSubscription('my-subscription', 'my-topic');
var pullEvent = await subscription.pull();
print(pullEvent.message.asString);
await pullEvent.acknowledge();
```
It is also possible to receive messages using push events instead of pulling
from the subscription. To do this the subscription should be configured as a
push subscription with an HTTP endpoint.
```dart
await pubsub.createSubscription(
'my-subscription',
'my-topic',
endpoint: Uri.parse('https://server.example.com/push'));
```
With this subscription all messages will be send to the URL provided in the
`endpoint` argument. The server needs to acknowledge the reception of the
message with a `200 OK` reply.
### Running tests
If you want to run the end-to-end tests, a Google Cloud project is required.
When running these tests the following environment variables need to be set:
GCLOUD_E2E_TEST_PROJECT
The value of the environment variable `GCLOUD_E2E_TEST_PROJECT` is the name
of the Google Cloud project to use. Authentication for testing uses
[Application Default Credentials][ADC] locally you can provide
`GOOGLE_APPLICATION_CREDENTIALS` or use
[`gcloud auth application-default login`][gcloud-adc].
You will also need to create indexes as follows:
```bash
gcloud --project "$GCLOUD_E2E_TEST_PROJECT" datastore indexes create test/index.yaml
```
[Datastore]: https://cloud.google.com/datastore/
[GCS]: https://cloud.google.com/storage/
[PubSub]: https://cloud.google.com/pubsub/
[googleapis]: https://pub.dartlang.org/packages/googleapis
[googleapisbeta]: https://pub.dartlang.org/packages/googleapis_beta
[googleapisauth]: https://pub.dartlang.org/packages/googleapis_beta
[appengine]: https://pub.dartlang.org/packages/appengine
[ADC]: https://cloud.google.com/docs/authentication/production
[gcloud-adc]: https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login