|
1 | | -# Pulumi Native Provider Boilerplate |
| 1 | +# Pulumi Turso Provider |
2 | 2 |
|
3 | | -This repository is a boilerplate showing how to create and locally test a native Pulumi provider. |
| 3 | +A native Pulumi provider for managing [Turso](https://turso.tech/) databases and groups. Turso is a distributed SQLite database platform built on libSQL. |
4 | 4 |
|
5 | | -## Authoring a Pulumi Native Provider |
| 5 | +## Features |
6 | 6 |
|
7 | | -This boilerplate creates a working Pulumi-owned provider named `xyz`. |
8 | | -It implements a random number generator that you can [build and test out for yourself](#test-against-the-example) and then replace the Random code with code specific to your provider. |
| 7 | +This provider allows you to manage the following Turso resources: |
9 | 8 |
|
| 9 | +- **Group** - Database groups with primary and replica locations |
| 10 | +- **Database** - SQLite databases within groups |
| 11 | +- **GroupToken** - Authentication tokens for database groups |
| 12 | +- **DatabaseToken** - Authentication tokens for individual databases |
10 | 13 |
|
11 | | -### Prerequisites |
| 14 | +## Installation |
| 15 | + |
| 16 | +### Go SDK |
| 17 | + |
| 18 | +```bash |
| 19 | +go get github.com/celest-dev/pulumi-turso/sdk/go/turso |
| 20 | +``` |
| 21 | + |
| 22 | +### Node.js SDK |
| 23 | + |
| 24 | +```bash |
| 25 | +npm install @celest-dev/pulumi-turso |
| 26 | +# or |
| 27 | +yarn add @celest-dev/pulumi-turso |
| 28 | +``` |
| 29 | + |
| 30 | +## Configuration |
12 | 31 |
|
13 | | -Prerequisites for this repository are already satisfied by the [Pulumi Devcontainer](https://github.com/pulumi/devcontainer) if you are using Github Codespaces, or VSCode. |
| 32 | +The provider requires the following configuration: |
14 | 33 |
|
15 | | -If you are not using VSCode, you will need to ensure the following tools are installed and present in your `$PATH`: |
| 34 | +| Name | Description | Environment Variable | |
| 35 | +|------|-------------|---------------------| |
| 36 | +| `organization` | Your Turso organization name (required) | `TURSO_ORGANIZATION` | |
| 37 | +| `apiToken` | Your Turso API token (optional if using Turso CLI auth) | `TURSO_API_TOKEN` | |
16 | 38 |
|
17 | | -* [`pulumictl`](https://github.com/pulumi/pulumictl#installation) |
18 | | -* [Go 1.21](https://golang.org/dl/) or 1.latest |
19 | | -* [NodeJS](https://nodejs.org/en/) 14.x. We recommend using [nvm](https://github.com/nvm-sh/nvm) to manage NodeJS installations. |
20 | | -* [Yarn](https://yarnpkg.com/) |
21 | | -* [TypeScript](https://www.typescriptlang.org/) |
22 | | -* [Python](https://www.python.org/downloads/) (called as `python3`). For recent versions of MacOS, the system-installed version is fine. |
23 | | -* [.NET](https://dotnet.microsoft.com/download) |
| 39 | +### Setting Configuration |
24 | 40 |
|
| 41 | +You can configure the provider using environment variables: |
| 42 | + |
| 43 | +```bash |
| 44 | +export TURSO_ORGANIZATION="your-org" |
| 45 | +export TURSO_API_TOKEN="your-api-token" |
| 46 | +``` |
25 | 47 |
|
26 | | -### Build & test the boilerplate XYZ provider |
| 48 | +Or via Pulumi configuration: |
27 | 49 |
|
28 | | -1. Create a new Github CodeSpaces environment using this repository. |
29 | | -1. Open a terminal in the CodeSpaces environment. |
30 | | -1. Run `make build install` to build and install the provider. |
31 | | -1. Run `make gen_examples` to generate the example programs in `examples/` off of the source `examples/yaml` example program. |
32 | | -1. Run `make up` to run the example program in `examples/yaml`. |
33 | | -1. Run `make down` to tear down the example program. |
| 50 | +```bash |
| 51 | +pulumi config set turso:organization your-org |
| 52 | +pulumi config set turso:apiToken your-api-token --secret |
| 53 | +``` |
34 | 54 |
|
35 | | -### Creating a new provider repository |
| 55 | +### Authentication |
36 | 56 |
|
37 | | -Pulumi offers this repository as a [GitHub template repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template) for convenience. From this repository: |
| 57 | +The provider supports two authentication methods: |
38 | 58 |
|
39 | | -1. Click "Use this template". |
40 | | -1. Set the following options: |
41 | | - * Owner: pulumi |
42 | | - * Repository name: pulumi-xyz-native (replace "xyz" with the name of your provider) |
43 | | - * Description: Pulumi provider for xyz |
44 | | - * Repository type: Public |
45 | | -1. Clone the generated repository. |
| 59 | +1. **API Token**: Set the `TURSO_API_TOKEN` environment variable or configure `apiToken` |
| 60 | +2. **Turso CLI**: If no API token is provided, the provider will use your Turso CLI authentication (run `turso auth login` first) |
46 | 61 |
|
47 | | -From the templated repository: |
| 62 | +## Resources |
48 | 63 |
|
49 | | -1. Run the following command to update files to use the name of your provider (third-party: use your GitHub organization/username): |
| 64 | +### Group |
50 | 65 |
|
51 | | - ```bash |
52 | | - make prepare NAME=foo REPOSITORY=github.com/pulumi/pulumi-foo ORG=myorg |
53 | | - ``` |
| 66 | +Creates a database group in a specific location with optional replicas. |
54 | 67 |
|
55 | | - This will do the following: |
56 | | - - rename folders in `provider/cmd` to `pulumi-resource-{NAME}` |
57 | | - - replace dependencies in `provider/go.mod` to reflect your repository name |
58 | | - - find and replace all instances of the boilerplate `xyz` with the `NAME` of your provider. |
59 | | - - find and replace all instances of the boilerplate `abc` with the `ORG` of your provider. |
60 | | - - replace all instances of the `github.com/pulumi/pulumi-xyz` repository with the `REPOSITORY` location |
| 68 | +#### Properties |
61 | 69 |
|
62 | | -#### Build the provider and install the plugin |
| 70 | +| Input | Type | Description | |
| 71 | +|-------|------|-------------| |
| 72 | +| `name` | string | Name of the group | |
| 73 | +| `primaryLocation` | string | Primary location code (e.g., "ord", "fra", "syd") | |
| 74 | +| `replicaLocations` | string[] | Optional list of replica location codes | |
| 75 | +| `extensions` | string | Optional SQLite extensions ("all" or "none") | |
63 | 76 |
|
64 | | - ```bash |
65 | | - $ make build install |
66 | | - ``` |
67 | | - |
68 | | -This will: |
| 77 | +| Output | Type | Description | |
| 78 | +|--------|------|-------------| |
| 79 | +| `uuid` | string | Unique identifier of the group | |
| 80 | +| `locations` | string[] | All locations where the group exists | |
| 81 | +| `primary` | string | Primary location of the group | |
69 | 82 |
|
70 | | -1. Create the SDK codegen binary and place it in a `./bin` folder (gitignored) |
71 | | -2. Create the provider binary and place it in the `./bin` folder (gitignored) |
72 | | -3. Generate the dotnet, Go, Node, and Python SDKs and place them in the `./sdk` folder |
73 | | -4. Install the provider on your machine. |
| 83 | +### Database |
74 | 84 |
|
75 | | -#### Test against the example |
76 | | - |
77 | | -```bash |
78 | | -$ cd examples/simple |
79 | | -$ yarn link @pulumi/xyz |
80 | | -$ yarn install |
81 | | -$ pulumi stack init test |
82 | | -$ pulumi up |
| 85 | +Creates a database within a group. |
| 86 | + |
| 87 | +#### Properties |
| 88 | + |
| 89 | +| Input | Type | Description | |
| 90 | +|-------|------|-------------| |
| 91 | +| `name` | string | Name of the database | |
| 92 | +| `group` | string | Name of the group to create the database in | |
| 93 | +| `sizeLimit` | string | Optional size limit (e.g., "500mb") | |
| 94 | +| `blockReads` | bool | Optional flag to block read operations | |
| 95 | +| `blockWrites` | bool | Optional flag to block write operations | |
| 96 | +| `seed` | object | Optional seed configuration for database initialization | |
| 97 | + |
| 98 | +| Output | Type | Description | |
| 99 | +|--------|------|-------------| |
| 100 | +| `dbId` | string | Unique database identifier | |
| 101 | +| `hostname` | string | Database hostname for connections | |
| 102 | +| `instances` | array | List of database instances | |
| 103 | + |
| 104 | +#### Database Seeding |
| 105 | + |
| 106 | +You can seed a new database from an existing database or a dump file: |
| 107 | + |
| 108 | +```yaml |
| 109 | +seed: |
| 110 | + type: "database" # or "dump" |
| 111 | + name: "source-db-name" # for type: database |
| 112 | + url: "https://..." # for type: dump |
| 113 | + timestamp: "2024-01-01T00:00:00Z" # optional point-in-time recovery |
83 | 114 | ``` |
84 | 115 |
|
85 | | -Now that you have completed all of the above steps, you have a working provider that generates a random string for you. |
| 116 | +### GroupToken |
| 117 | +
|
| 118 | +Creates an authentication token for a database group. |
| 119 | +
|
| 120 | +#### Properties |
| 121 | +
|
| 122 | +| Input | Type | Description | |
| 123 | +|-------|------|-------------| |
| 124 | +| `group` | string | Name of the group | |
| 125 | +| `expiration` | string | Optional expiration (e.g., "2w", "30d", "never") | |
| 126 | +| `authorization` | string | Authorization level: "full-access" or "read-only" | |
| 127 | + |
| 128 | +| Output | Type | Description | |
| 129 | +|--------|------|-------------| |
| 130 | +| `token` | string (secret) | The generated JWT token | |
| 131 | +| `expiresAt` | string | Token expiration timestamp | |
| 132 | + |
| 133 | +### DatabaseToken |
| 134 | + |
| 135 | +Creates an authentication token for a specific database. |
| 136 | + |
| 137 | +#### Properties |
| 138 | + |
| 139 | +| Input | Type | Description | |
| 140 | +|-------|------|-------------| |
| 141 | +| `database` | string | Name of the database | |
| 142 | +| `expiration` | string | Optional expiration (e.g., "2w", "30d", "never") | |
| 143 | +| `authorization` | string | Authorization level: "full-access" or "read-only" | |
| 144 | + |
| 145 | +| Output | Type | Description | |
| 146 | +|--------|------|-------------| |
| 147 | +| `token` | string (secret) | The generated JWT token | |
| 148 | +| `expiresAt` | string | Token expiration timestamp | |
| 149 | + |
| 150 | +## Examples |
| 151 | + |
| 152 | +### Go |
| 153 | + |
| 154 | +```go |
| 155 | +package main |
| 156 | +
|
| 157 | +import ( |
| 158 | + "github.com/celest-dev/pulumi-turso/sdk/go/turso" |
| 159 | + "github.com/pulumi/pulumi/sdk/v3/go/pulumi" |
| 160 | +) |
| 161 | +
|
| 162 | +func main() { |
| 163 | + pulumi.Run(func(ctx *pulumi.Context) error { |
| 164 | + // Create a database group |
| 165 | + group, err := turso.NewGroup(ctx, "my-group", &turso.GroupArgs{ |
| 166 | + Name: pulumi.String("my-group"), |
| 167 | + PrimaryLocation: pulumi.String("ord"), |
| 168 | + }) |
| 169 | + if err != nil { |
| 170 | + return err |
| 171 | + } |
| 172 | +
|
| 173 | + // Create a database in the group |
| 174 | + db, err := turso.NewDatabase(ctx, "my-db", &turso.DatabaseArgs{ |
| 175 | + Name: pulumi.String("my-db"), |
| 176 | + Group: group.Name, |
| 177 | + }) |
| 178 | + if err != nil { |
| 179 | + return err |
| 180 | + } |
| 181 | +
|
| 182 | + // Create a read-only token for the database |
| 183 | + token, err := turso.NewDatabaseToken(ctx, "my-db-token", &turso.DatabaseTokenArgs{ |
| 184 | + Database: db.Name, |
| 185 | + Expiration: pulumi.String("2w"), |
| 186 | + Authorization: turso.DatabaseTokenAuthorization_Read_Only, |
| 187 | + }) |
| 188 | + if err != nil { |
| 189 | + return err |
| 190 | + } |
| 191 | +
|
| 192 | + // Export outputs |
| 193 | + ctx.Export("hostname", db.Hostname) |
| 194 | + ctx.Export("token", token.Token) |
| 195 | +
|
| 196 | + return nil |
| 197 | + }) |
| 198 | +} |
| 199 | +``` |
86 | 200 |
|
87 | | -#### A brief repository overview |
| 201 | +### Node.js / TypeScript |
| 202 | + |
| 203 | +```typescript |
| 204 | +import * as pulumi from "@pulumi/pulumi"; |
| 205 | +import * as turso from "@celest-dev/pulumi-turso"; |
| 206 | +
|
| 207 | +// Create a database group |
| 208 | +const group = new turso.Group("my-group", { |
| 209 | + name: "my-group", |
| 210 | + primaryLocation: "ord", |
| 211 | +}); |
| 212 | +
|
| 213 | +// Create a database in the group |
| 214 | +const db = new turso.Database("my-db", { |
| 215 | + name: "my-db", |
| 216 | + group: group.name, |
| 217 | +}); |
| 218 | +
|
| 219 | +// Create a read-only token for the database |
| 220 | +const token = new turso.DatabaseToken("my-db-token", { |
| 221 | + database: db.name, |
| 222 | + expiration: "2w", |
| 223 | + authorization: "read-only", |
| 224 | +}); |
| 225 | +
|
| 226 | +// Export outputs |
| 227 | +export const hostname = db.hostname; |
| 228 | +export const dbToken = token.token; |
| 229 | +``` |
88 | 230 |
|
89 | | -You now have: |
| 231 | +### YAML |
| 232 | + |
| 233 | +```yaml |
| 234 | +name: turso-example |
| 235 | +runtime: yaml |
| 236 | +resources: |
| 237 | + my-group: |
| 238 | + type: turso:Group |
| 239 | + properties: |
| 240 | + name: my-group |
| 241 | + primaryLocation: ord |
| 242 | + my-db: |
| 243 | + type: turso:Database |
| 244 | + properties: |
| 245 | + name: my-db |
| 246 | + group: ${my-group.name} |
| 247 | + my-db-token: |
| 248 | + type: turso:DatabaseToken |
| 249 | + properties: |
| 250 | + database: ${my-db.name} |
| 251 | + expiration: 2w |
| 252 | + authorization: read-only |
| 253 | +outputs: |
| 254 | + hostname: ${my-db.hostname} |
| 255 | + token: ${my-db-token.token} |
| 256 | +``` |
90 | 257 |
|
91 | | -1. A `provider/` folder containing the building and implementation logic |
92 | | - 1. `cmd/pulumi-resource-xyz/main.go` - holds the provider's sample implementation logic. |
93 | | -2. `deployment-templates` - a set of files to help you around deployment and publication |
94 | | -3. `sdk` - holds the generated code libraries created by `pulumi-gen-xyz/main.go` |
95 | | -4. `examples` a folder of Pulumi programs to try locally and/or use in CI. |
96 | | -5. A `Makefile` and this `README`. |
| 258 | +## Development |
97 | 259 |
|
98 | | -#### Additional Details |
| 260 | +### Prerequisites |
99 | 261 |
|
100 | | -This repository depends on the pulumi-go-provider library. For more details on building providers, please check |
101 | | -the [Pulumi Go Provider docs](https://github.com/pulumi/pulumi-go-provider). |
| 262 | +- [Go 1.24+](https://golang.org/dl/) |
| 263 | +- [Pulumi CLI](https://www.pulumi.com/docs/get-started/install/) |
| 264 | +- [Node.js 20+](https://nodejs.org/) (for Node.js SDK) |
102 | 265 |
|
103 | | -### Build Examples |
| 266 | +### Building |
104 | 267 |
|
105 | | -Create an example program using the resources defined in your provider, and place it in the `examples/` folder. |
| 268 | +```bash |
| 269 | +# Build the provider and SDKs |
| 270 | +make build |
106 | 271 |
|
107 | | -You can now repeat the steps for [build, install, and test](#test-against-the-example). |
| 272 | +# Install the provider locally |
| 273 | +make install |
108 | 274 |
|
109 | | -## Configuring CI and releases |
| 275 | +# Run tests |
| 276 | +make test |
| 277 | +``` |
110 | 278 |
|
111 | | -1. Follow the instructions laid out in the [deployment templates](./deployment-templates/README-DEPLOYMENT.md). |
| 279 | +### Running Examples |
| 280 | + |
| 281 | +```bash |
| 282 | +# Run the YAML example |
| 283 | +cd examples/yaml |
| 284 | +pulumi up |
| 285 | +
|
| 286 | +# Run the Go example |
| 287 | +cd examples/go |
| 288 | +go mod tidy |
| 289 | +pulumi up |
| 290 | +``` |
112 | 291 |
|
113 | | -## References |
| 292 | +## License |
114 | 293 |
|
115 | | -Other resources/examples for implementing providers: |
116 | | -* [Pulumi Command provider](https://github.com/pulumi/pulumi-command/blob/master/provider/pkg/provider/provider.go) |
117 | | -* [Pulumi Go Provider repository](https://github.com/pulumi/pulumi-go-provider) |
| 294 | +Apache 2.0 - See [LICENSE](./LICENSE) for details. |
0 commit comments