Skip to content

Commit

Permalink
Add dbt-cloud environment create command (#91)
Browse files Browse the repository at this point in the history
* Add DbtCloudEnvironmentCreateCommand class

* Fix environment commands now inherit DbtCloudProjectCommand

* Add unit test

* Add test_cli_environment_create_and_delete integration test

* Update README

* Fix docstrings

---------

Co-authored-by: Simo Tumelius <simo@datamie.fi>
  • Loading branch information
stumelius and datamie-simo committed Aug 3, 2023
1 parent 26df2cc commit 8481929
Show file tree
Hide file tree
Showing 13 changed files with 291 additions and 23 deletions.
24 changes: 17 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ For more information on a command, run `dbt-cloud <command> --help`. For more in
| Project | [dbt-cloud project get](#dbt-cloud-project-get) || GET `https://{dbt_cloud_host}/api/v3/accounts/{account_id}/projects/{id}/` |
| Project | [dbt-cloud project list](#dbt-cloud-project-list) || GET `https://{dbt_cloud_host}/api/v3/accounts/{account_id}/projects/` |
| Project | [dbt-cloud project update](#dbt-cloud-project-update) || POST `https://{dbt_cloud_host}/api/v3/accounts/{account_id}/projects/{id}/` |
| Environment | [dbt-cloud environment create](#dbt-cloud-environment-create) | | POST `https://{dbt_cloud_host}/api/v3/accounts/{account_id}/environments/` |
| Environment | [dbt-cloud environment create](#dbt-cloud-environment-create) | | POST `https://{dbt_cloud_host}/api/v3/accounts/{account_id}/environments/` |
| Environment | [dbt-cloud environment delete](#dbt-cloud-environment-delete) || DELETE `https://{dbt_cloud_host}/api/v3/accounts/{account_id}/environments/{id}/` |
| Environment | [dbt-cloud environment get](#dbt-cloud-environment-get) || GET `https://{dbt_cloud_host}/api/v3/accounts/{account_id}/environments/{id}/` |
| Environment | [dbt-cloud environment list](#dbt-cloud-environment-list) || GET `https://{dbt_cloud_host}/api/v3/accounts/{account_id}/environments/` |
Expand Down Expand Up @@ -165,33 +165,43 @@ dbt-cloud project list

[Click to view sample response](tests/data/project_list_response.json)

## dbt-cloud environment create
This command a new dbt Cloud environment in a given project.

### Usage
```bash
dbt-cloud environment create --account-id 123456 --project-id 123457 --name "My environment" --dbt-version "1.5.0-latest"
```

[Click to view sample response](tests/data/environment_create_response.json)

## dbt-cloud environment delete
This command deletes a dbt Cloud environment in a given account.
This command deletes a dbt Cloud environment in a given project.

### Usage
```bash
dbt-cloud environment delete --environment-id 222062
dbt-cloud environment delete --account-id 123456 --project-id 123457 --environment-id 40480
```

[Click to view sample response](tests/data/environment_delete_response.json)


## dbt-cloud environment list
This command retrieves environments in a given account.
This command retrieves environments in a given project.

### Usage
```bash
dbt-cloud environment list --account-id 16182 --limit 1
dbt-cloud environment list --account-id 123456 --project-id 123457 --limit 1
```

[Click to view sample response](tests/data/environment_list_response.json)

## dbt-cloud environment get
This command retrieves information about an environment in a given account.
This command retrieves information about an environment in a given project.

### Usage
```bash
dbt-cloud environment get --account-id 54321 --environment-id 67890
dbt-cloud environment get --account-id 123456 --project-id 123457 --environment-id 67890
```

[Click to view sample response](tests/data/environment_get_response.json)
Expand Down
8 changes: 8 additions & 0 deletions dbt_cloud/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
DbtCloudProjectDeleteCommand,
DbtCloudEnvironmentListCommand,
DbtCloudEnvironmentGetCommand,
DbtCloudEnvironmentCreateCommand,
DbtCloudEnvironmentDeleteCommand,
DbtCloudAccountListCommand,
DbtCloudAccountGetCommand,
Expand Down Expand Up @@ -397,6 +398,13 @@ def get(**kwargs):
response = execute_and_print(command)


@environment.command(help=DbtCloudEnvironmentCreateCommand.get_description())
@DbtCloudEnvironmentCreateCommand.click_options
def create(**kwargs):
command = DbtCloudEnvironmentCreateCommand.from_click_options(**kwargs)
response = execute_and_print(command)


@environment.command(help=DbtCloudEnvironmentDeleteCommand.get_description())
@DbtCloudEnvironmentDeleteCommand.click_options
def delete(**kwargs):
Expand Down
1 change: 1 addition & 0 deletions dbt_cloud/command/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
DbtCloudEnvironmentListCommand,
DbtCloudEnvironmentGetCommand,
DbtCloudEnvironmentDeleteCommand,
DbtCloudEnvironmentCreateCommand,
)
from .account import DbtCloudAccountListCommand, DbtCloudAccountGetCommand
from .audit_log import DbtCloudAuditLogGetCommand
Expand Down
1 change: 1 addition & 0 deletions dbt_cloud/command/environment/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .list import DbtCloudEnvironmentListCommand
from .get import DbtCloudEnvironmentGetCommand
from .create import DbtCloudEnvironmentCreateCommand
from .delete import DbtCloudEnvironmentDeleteCommand
63 changes: 63 additions & 0 deletions dbt_cloud/command/environment/create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import requests
from typing import Optional
from pydantic import Field
from dbt_cloud.command.command import DbtCloudProjectCommand
from dbt_cloud.field import DBT_VERSION_FIELD


class DbtCloudEnvironmentCreateCommand(DbtCloudProjectCommand):
"""Creates a new dbt Cloud environment in a given project."""

name: str = Field(
description="Name of the environment.",
)
id: Optional[int]
connection_id: Optional[int] = Field(
description="Connection ID to use for this environment.",
)
credentials_id: Optional[int] = Field(
description="Credentials ID to use for this environment.",
)
created_by_id: Optional[int] = Field(
description="User ID of the user who created this environment.",
)
dbt_project_subdirectory: Optional[str] = Field(
description="Subdirectory of the dbt project to use for this environment.",
)
use_custom_branch: bool = Field(
False,
description="Whether to use a custom branch for this environment.",
)
custom_branch: Optional[str] = Field(
description="Custom branch to use for this environment.",
)
dbt_version: Optional[str] = DBT_VERSION_FIELD
raw_dbt_version: Optional[str] = Field(
description="Raw dbt version to use for this environment.",
)
supports_docs: bool = Field(
False,
description="Whether this environment supports docs.",
)
repository_id: Optional[int] = Field(
description="Repository ID to use for this environment.",
)
state: int = Field(
1,
description="State of the environment. 1 = Active.",
)
custom_environment_variables: Optional[dict] = Field(
description="Custom environment variables to use for this environment.",
)

@property
def api_url(self) -> str:
return f"{super().api_url}/environments"

def execute(self) -> requests.Response:
response = requests.post(
url=self.api_url,
headers=self.request_headers,
json=self.get_payload(exclude_empty=True),
)
return response
6 changes: 3 additions & 3 deletions dbt_cloud/command/environment/delete.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import requests
from pydantic import Field
from dbt_cloud.command.command import DbtCloudAccountCommand
from dbt_cloud.command.command import DbtCloudProjectCommand


class DbtCloudEnvironmentDeleteCommand(DbtCloudAccountCommand):
"""Deletes a dbt Cloud environment in a given account."""
class DbtCloudEnvironmentDeleteCommand(DbtCloudProjectCommand):
"""Deletes a dbt Cloud environment in a given project."""

environment_id: int = Field(
description="ID of the dbt Cloud environment to delete.",
Expand Down
7 changes: 3 additions & 4 deletions dbt_cloud/command/environment/get.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import requests
from pydantic import PrivateAttr
from dbt_cloud.command.command import DbtCloudAccountCommand
from dbt_cloud.command.command import DbtCloudProjectCommand
from dbt_cloud.field import ACCOUNT_ID_FIELD, ENVIRONMENT_ID_FIELD


class DbtCloudEnvironmentGetCommand(DbtCloudAccountCommand):
"""Retrieves information about an environment in a given account."""
class DbtCloudEnvironmentGetCommand(DbtCloudProjectCommand):
"""Retrieves information about an environment in a given project."""

environment_id: int = ENVIRONMENT_ID_FIELD
account_id: int = ACCOUNT_ID_FIELD
Expand Down
6 changes: 3 additions & 3 deletions dbt_cloud/command/environment/list.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import requests
from typing import Optional
from pydantic import Field
from dbt_cloud.command.command import DbtCloudAccountCommand
from dbt_cloud.command.command import DbtCloudProjectCommand
from dbt_cloud.field import LIMIT_FIELD, OFFSET_FIELD, DBT_VERSION_FIELD


class DbtCloudEnvironmentListCommand(DbtCloudAccountCommand):
"""Retrieves environments in a given account."""
class DbtCloudEnvironmentListCommand(DbtCloudProjectCommand):
"""Retrieves environments in a given project."""

limit: Optional[int] = LIMIT_FIELD
dbt_version: Optional[str] = DBT_VERSION_FIELD
Expand Down
2 changes: 1 addition & 1 deletion dbt_cloud/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,5 @@ def get_env(name: str, default=None, allow_none: bool = False):
description="Offset for the returned rows. Must be a positive integer.",
)
DBT_VERSION_FIELD = Field(
description="Filter by dbt version (e.g., '1.4.0-latest')",
description="dbt version (e.g., '1.4.0-latest')",
)
18 changes: 17 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
DbtCloudEnvironmentListCommand,
DbtCloudEnvironmentGetCommand,
DbtCloudEnvironmentDeleteCommand,
DbtCloudEnvironmentCreateCommand,
DbtCloudAccountListCommand,
DbtCloudAccountGetCommand,
DbtCloudAuditLogGetCommand,
Expand Down Expand Up @@ -219,12 +220,27 @@ def load_response(response_name):
pytest.param(
"environment_delete",
DbtCloudEnvironmentDeleteCommand(
api_token=API_TOKEN, account_id=ACCOUNT_ID, environment_id=222062
api_token=API_TOKEN,
account_id=ACCOUNT_ID,
project_id=PROJECT_ID,
environment_id=222062,
),
load_response("environment_delete_response"),
"delete",
marks=pytest.mark.environment,
),
pytest.param(
"environment_create",
DbtCloudEnvironmentCreateCommand(
api_token=API_TOKEN,
account_id=ACCOUNT_ID,
project_id=PROJECT_ID,
name="pytest environment",
),
load_response("environment_create_response"),
"post",
marks=pytest.mark.environment,
),
pytest.param(
"account_list",
DbtCloudAccountListCommand(api_token=API_TOKEN),
Expand Down
111 changes: 111 additions & 0 deletions tests/data/environment_create_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
{
"status": {
"code": 201,
"is_success": true,
"user_message": "Success!",
"developer_message": ""
},
"data": {
"id": 222601,
"account_id": 123456,
"project_id": 123457,
"credentials_id": null,
"name": "pytest environment",
"dbt_version": "1.6.0-latest",
"raw_dbt_version": "1.6.0-latest",
"type": "deployment",
"use_custom_branch": false,
"custom_branch": null,
"supports_docs": false,
"state": 1,
"created_at": null,
"updated_at": "2023-08-03 11:53:02.868229+00:00",
"project": {
"name": "jaffle_shop",
"account_id": 123456,
"connection_id": 32544,
"repository_id": 40480,
"semantic_layer_config_id": null,
"id": 26597,
"created_at": "2021-04-14 20:23:00.395285+00:00",
"updated_at": "2021-11-16 16:32:43.960836+00:00",
"skipped_setup": false,
"state": 1,
"dbt_project_subdirectory": null,
"connection": {
"id": 32544,
"account_id": 123456,
"project_id": 123457,
"name": "Bigquery",
"type": "bigquery",
"created_by_id": 1321515,
"created_by_service_token_id": null,
"details": {
"project_id": "ANONYMIZED",
"timeout_seconds": 300,
"private_key_id": "ANONYMIZED",
"client_email": "ANONYMIZED",
"client_id": "ANONYMIZED",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/dbt-user%40ANONYMIZED",
"priority": null,
"retries": 1,
"scopes": null,
"location": null,
"maximum_bytes_billed": 0,
"execution_project": null,
"impersonate_service_account": null,
"job_retry_deadline_seconds": 0,
"job_creation_timeout_seconds": 0,
"is_configured_for_oauth": false,
"gcs_bucket": null,
"dataproc_region": null,
"dataproc_cluster_name": null
},
"state": 1,
"created_at": "2021-11-16 16:26:01.571115+00:00",
"updated_at": "2022-05-18 06:27:34.729528+00:00",
"private_link_endpoint_id": null
},
"repository": {
"id": 40480,
"account_id": 123456,
"project_id": 123457,
"full_name": "ANONYMIZED",
"remote_url": "ANONYMIZED",
"remote_backend": "github",
"git_clone_strategy": "github_app",
"deploy_key_id": 39445,
"repository_credentials_id": null,
"github_installation_id": 19320059,
"github_webhook_id": null,
"pull_request_url_template": "ANONYMIZED",
"state": 1,
"created_at": "2021-11-16 16:26:24.412439+00:00",
"updated_at": "2021-11-16 16:26:24.412455+00:00",
"deploy_key": {
"id": 39445,
"account_id": 123456,
"state": 1,
"public_key": "ssh-rsa ANONYMIZED"
},
"github_repo": "ANONYMIZED",
"name": "dbt-cloud-cli",
"git_provider_id": 9437,
"gitlab": null,
"git_provider": null
},
"group_permissions": null,
"docs_job_id": null,
"freshness_job_id": null,
"docs_job": null,
"freshness_job": null
},
"jobs": null,
"credentials": null,
"custom_environment_variables": null,
"deployment_type": null
}
}
2 changes: 1 addition & 1 deletion tests/data/environment_delete_response.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"data": {
"dbt_project_subdirectory": null,
"project_id": 247181,
"id": 222062,
"id": 40480,
"account_id": 16182,
"connection_id": 135120,
"repository_id": null,
Expand Down
Loading

0 comments on commit 8481929

Please sign in to comment.