diff --git a/README.md b/README.md index 933863d..733b53a 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ For more information on a command, run `dbt-cloud --help`. For more in | Project | [dbt-cloud project delete](#dbt-cloud-project-delete) | ✅ | DELETE `https://{dbt_cloud_host}/api/v3/accounts/{account_id}/projects/{id}/` | | 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}/` | +| 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 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}/` | @@ -165,6 +165,17 @@ dbt-cloud project list [Click to view sample response](tests/data/project_list_response.json) + +## dbt-cloud project update +This command updates a project in a given account. + +### Usage +```bash +dbt-cloud project update --project-id 273745 --name "My project renamed" +``` + +[Click to view sample response](tests/data/project_update_response.json) + ## dbt-cloud environment create This command a new dbt Cloud environment in a given project. diff --git a/dbt_cloud/cli.py b/dbt_cloud/cli.py index 3366442..edb433b 100644 --- a/dbt_cloud/cli.py +++ b/dbt_cloud/cli.py @@ -20,6 +20,7 @@ DbtCloudProjectListCommand, DbtCloudProjectCreateCommand, DbtCloudProjectDeleteCommand, + DbtCloudProjectUpdateCommand, DbtCloudEnvironmentListCommand, DbtCloudEnvironmentGetCommand, DbtCloudEnvironmentCreateCommand, @@ -386,6 +387,13 @@ def delete(**kwargs): response = execute_and_print(command) +@project.command(help=DbtCloudProjectUpdateCommand.get_description()) +@DbtCloudProjectUpdateCommand.click_options +def update(**kwargs): + command = DbtCloudProjectUpdateCommand.from_click_options(**kwargs) + response = execute_and_print(command) + + @environment.command(help=DbtCloudEnvironmentListCommand.get_description()) @DbtCloudEnvironmentListCommand.click_options def list(**kwargs): diff --git a/dbt_cloud/command/__init__.py b/dbt_cloud/command/__init__.py index 51465b4..eeb8480 100644 --- a/dbt_cloud/command/__init__.py +++ b/dbt_cloud/command/__init__.py @@ -18,6 +18,7 @@ DbtCloudProjectGetCommand, DbtCloudProjectCreateCommand, DbtCloudProjectDeleteCommand, + DbtCloudProjectUpdateCommand, ) from .environment import ( DbtCloudEnvironmentListCommand, diff --git a/dbt_cloud/command/project/__init__.py b/dbt_cloud/command/project/__init__.py index 14770a6..3cfc6a8 100644 --- a/dbt_cloud/command/project/__init__.py +++ b/dbt_cloud/command/project/__init__.py @@ -2,3 +2,4 @@ from .get import DbtCloudProjectGetCommand from .create import DbtCloudProjectCreateCommand from .delete import DbtCloudProjectDeleteCommand +from .update import DbtCloudProjectUpdateCommand diff --git a/dbt_cloud/command/project/update.py b/dbt_cloud/command/project/update.py new file mode 100644 index 0000000..18fb20e --- /dev/null +++ b/dbt_cloud/command/project/update.py @@ -0,0 +1,22 @@ +import requests +from pydantic import Field +from dbt_cloud.command.project.create import DbtCloudProjectCreateCommand + + +class DbtCloudProjectUpdateCommand(DbtCloudProjectCreateCommand): + """Updates a project in a given account.""" + + project_id: int = Field(description="ID of the project to update.") + + @property + def api_url(self) -> str: + return f"{super().api_url}/{self.project_id}" + + def execute(self) -> requests.Response: + payload = self.get_payload(exclude_empty=True) + # Rename project_id to id + payload["id"] = payload.pop("project_id") + response = requests.post( + url=self.api_url, headers=self.request_headers, json=payload + ) + return response diff --git a/tests/conftest.py b/tests/conftest.py index 1e1c9d1..6b575ad 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -12,6 +12,7 @@ DbtCloudProjectListCommand, DbtCloudProjectCreateCommand, DbtCloudProjectDeleteCommand, + DbtCloudProjectUpdateCommand, DbtCloudRunCancelCommand, DbtCloudRunGetArtifactCommand, DbtCloudRunGetCommand, @@ -192,6 +193,19 @@ def load_response(response_name): "post", marks=pytest.mark.project, ), + pytest.param( + "project_update", + DbtCloudProjectUpdateCommand( + api_token=API_TOKEN, + account_id=ACCOUNT_ID, + project_id=PROJECT_ID, + name="My test project", + dbt_project_subdirectory="dbt/", + ), + load_response("project_update_response"), + "post", + marks=pytest.mark.project, + ), pytest.param( "project_delete", DbtCloudProjectDeleteCommand( diff --git a/tests/data/project_update_response.json b/tests/data/project_update_response.json new file mode 100644 index 0000000..244c8e8 --- /dev/null +++ b/tests/data/project_update_response.json @@ -0,0 +1,28 @@ +{ + "status": { + "code": 200, + "is_success": true, + "user_message": "Success!", + "developer_message": "" + }, + "data": { + "name": "My project renamed", + "account_id": 123456, + "connection_id": null, + "repository_id": null, + "semantic_layer_config_id": null, + "id": 273745, + "created_at": "2023-08-02 08:09:57.922958+00:00", + "updated_at": "2023-08-21 08:31:36.941327+00:00", + "skipped_setup": false, + "state": 1, + "dbt_project_subdirectory": null, + "connection": null, + "repository": null, + "group_permissions": [], + "docs_job_id": null, + "freshness_job_id": null, + "docs_job": null, + "freshness_job": null + } +} \ No newline at end of file diff --git a/tests/test_cli.py b/tests/test_cli.py index 196fd54..64693d7 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -241,6 +241,32 @@ def test_cli_project_list_and_get(runner, account_id): assert response["data"]["id"] == project_id +@pytest.mark.project +@pytest.mark.integration +def test_cli_project_update(runner, account_id, dbt_cloud_project): + project_id = dbt_cloud_project["id"] + + # Project update + result = runner.invoke( + cli, + [ + "project", + "update", + "--account-id", + account_id, + "--project-id", + project_id, + "--name", + "pytest project updated", + ], + ) + print(result.output) + assert result.exit_code == 0, result.output + response = json.loads(result.output) + assert response["data"]["id"] == project_id + assert response["data"]["name"] == "pytest project updated" + + @pytest.mark.connection @pytest.mark.integration @pytest.mark.parametrize(