Skip to content

Commit 83d4c19

Browse files
authored
Merge pull request #49 from getindata/release-0.11.0
Release 0.11.0
2 parents 2e335a5 + ce08392 commit 83d4c19

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+5908
-183
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
repos:
22

33
- repo: https://github.com/pre-commit/mirrors-isort
4-
rev: v5.9.3
4+
rev: v5.10.1
55
hooks:
66
- id: isort
77

@@ -33,7 +33,7 @@ repos:
3333
]
3434

3535
- repo: https://github.com/pre-commit/mirrors-mypy
36-
rev: v0.930
36+
rev: v0.931
3737
hooks:
3838
- id: mypy
3939
additional_dependencies:

CHANGELOG.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22

33
## [Unreleased]
44

5+
## [0.11.0] - 2022-01-18
6+
7+
### Added
8+
9+
- `dp update` command
10+
- `dp publish` command for creation of dbt package out of the project.
11+
12+
### Changed
13+
14+
- Docker response in `deploy` and `compile` gets printed as processed strings instead of plain dictionaries.
15+
- `dp compile` parses content of `datahub.yml` and replaces Jinja variables in the form of `var` or `env_var`.
16+
- `dags_path` is read from an enved `airflow.yml` file.
17+
518
## [0.10.0] - 2022-01-12
619

720
### Changed
@@ -131,7 +144,9 @@
131144
- Draft of `dp init`, `dp create`, `dp template new`, `dp template list` and `dp dbt`
132145
- Draft of `dp compile` and `dp deploy`
133146

134-
[Unreleased]: https://github.com/getindata/data-pipelines-cli/compare/0.10.0...HEAD
147+
[Unreleased]: https://github.com/getindata/data-pipelines-cli/compare/0.11.0...HEAD
148+
149+
[0.11.0]: https://github.com/getindata/data-pipelines-cli/compare/0.10.0...0.11.0
135150

136151
[0.10.0]: https://github.com/getindata/data-pipelines-cli/compare/0.9.0...0.10.0
137152

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ directly to a template repository. If `<LINK_TO_TEMPLATE_REPOSITORY>` proves to
4747

4848
`dp template-list` lists all added templates.
4949

50+
### Project update
51+
52+
To update your pipeline project use `dp update <PIPELINE_PROJECT-PATH>`. It will sync your existing project with updated
53+
template version selected by `--vcs-ref` option (default `HEAD`).
54+
5055
### Project deployment
5156

5257
`dp deploy` will sync with your bucket provider. The provider will be chosen automatically based on the remote URL.

data_pipelines_cli/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,8 @@
1-
version = "0.10.0"
1+
"""
2+
data-pipelines-cli (dp) is a CLI tool designed for data platform.
3+
4+
dp helps data analysts to create, maintain and make full use of their data
5+
pipelines.
6+
"""
7+
8+
version = "0.11.0"

data_pipelines_cli/cli.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
from .cli_commands.deploy import deploy_command
99
from .cli_commands.init import init_command
1010
from .cli_commands.prepare_env import prepare_env_command
11+
from .cli_commands.publish import publish_command
1112
from .cli_commands.run import run_command
1213
from .cli_commands.template import list_templates_command
1314
from .cli_commands.test import test_command
15+
from .cli_commands.update import update_command
1416
from .cli_utils import echo_error
1517
from .errors import DataPipelinesError
1618

@@ -35,6 +37,8 @@ def cli() -> None:
3537
_cli.add_command(deploy_command)
3638
_cli.add_command(init_command)
3739
_cli.add_command(prepare_env_command)
40+
_cli.add_command(publish_command)
3841
_cli.add_command(run_command)
3942
_cli.add_command(list_templates_command)
4043
_cli.add_command(test_command)
44+
_cli.add_command(update_command)

data_pipelines_cli/cli_commands/clean.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def _remove_build_dir() -> None:
1919

2020

2121
def clean() -> None:
22-
"""Deletes local working directories"""
22+
"""Delete local working directories."""
2323
_dbt_clean()
2424
_remove_build_dir()
2525

data_pipelines_cli/cli_commands/compile.py

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,25 @@
22
import shutil
33

44
import click
5+
import yaml
56

67
from ..cli_constants import BUILD_DIR, IMAGE_TAG_TO_REPLACE
7-
from ..cli_utils import echo_info
8+
from ..cli_utils import echo_error, echo_info, echo_warning
89
from ..config_generation import (
910
copy_config_dir_to_build_dir,
1011
copy_dag_dir_to_build_dir,
1112
generate_profiles_yml,
1213
)
1314
from ..data_structures import DockerArgs
14-
from ..dbt_utils import run_dbt_command
15-
from ..errors import DockerNotInstalledError
15+
from ..dbt_utils import read_dbt_vars_from_configs, run_dbt_command
16+
from ..docker_response_reader import DockerResponseReader
17+
from ..errors import (
18+
DataPipelinesError,
19+
DockerErrorResponseError,
20+
DockerNotInstalledError,
21+
)
1622
from ..io_utils import replace
17-
18-
19-
def _replace_image_tag(k8s_config: pathlib.Path, docker_args: DockerArgs) -> None:
20-
echo_info(
21-
f"Replacing {IMAGE_TAG_TO_REPLACE} with commit SHA = {docker_args.commit_sha}"
22-
)
23-
replace(k8s_config, IMAGE_TAG_TO_REPLACE, docker_args.commit_sha)
23+
from ..jinja import replace_vars_with_values
2424

2525

2626
def _docker_build(docker_args: DockerArgs) -> None:
@@ -38,14 +38,15 @@ def _docker_build(docker_args: DockerArgs) -> None:
3838
docker_client = docker.from_env()
3939
docker_tag = docker_args.docker_build_tag()
4040
_, logs_generator = docker_client.images.build(path=".", tag=docker_tag)
41-
click.echo(
42-
"".join(
43-
map(
44-
lambda log: log["stream"],
45-
filter(lambda log: "stream" in log, logs_generator),
46-
)
41+
try:
42+
DockerResponseReader(logs_generator).click_echo_ok_responses()
43+
except DockerErrorResponseError as err:
44+
echo_error(err.message)
45+
raise DataPipelinesError(
46+
"Error raised when pushing Docker image. Ensure that "
47+
"Docker image you try to push exists. Maybe try running "
48+
"'dp compile' first?"
4749
)
48-
)
4950

5051

5152
def _dbt_compile(env: str) -> None:
@@ -66,16 +67,40 @@ def _copy_dbt_manifest() -> None:
6667

6768

6869
def _replace_k8s_settings(docker_args: DockerArgs) -> None:
69-
k8s_config: pathlib.Path = BUILD_DIR.joinpath("dag", "config", "base", "k8s.yml")
70-
_replace_image_tag(k8s_config, docker_args)
70+
k8s_config = BUILD_DIR.joinpath("dag", "config", "base", "k8s.yml")
71+
echo_info(
72+
f"Replacing {IMAGE_TAG_TO_REPLACE} with commit SHA = {docker_args.commit_sha}"
73+
)
74+
replace(k8s_config, IMAGE_TAG_TO_REPLACE, docker_args.commit_sha)
75+
76+
77+
def _replace_datahub_with_jinja_vars(env: str) -> None:
78+
datahub_config_path: pathlib.Path = BUILD_DIR.joinpath(
79+
"dag", "config", "base", "datahub.yml"
80+
)
81+
82+
if not datahub_config_path.exists():
83+
echo_warning(
84+
f"File config/base/datahub.yml does not exist in {BUILD_DIR}. "
85+
"Content will not be replaced."
86+
)
87+
return
88+
89+
echo_info(f"Replacing Jinja variables in {datahub_config_path}.")
90+
with open(datahub_config_path, "r") as datahub_config_file:
91+
updated_config = replace_vars_with_values(
92+
yaml.safe_load(datahub_config_file), read_dbt_vars_from_configs(env)
93+
)
94+
with open(datahub_config_path, "w") as datahub_config_file:
95+
yaml.dump(updated_config, datahub_config_file)
7196

7297

7398
def compile_project(
7499
env: str,
75100
docker_build: bool = False,
76101
) -> None:
77102
"""
78-
Create local working directories and build artifacts
103+
Create local working directories and build artifacts.
79104
80105
:param env: Name of the environment
81106
:type env: str
@@ -88,6 +113,7 @@ def compile_project(
88113

89114
docker_args = DockerArgs(env)
90115
_replace_k8s_settings(docker_args)
116+
_replace_datahub_with_jinja_vars(env)
91117

92118
_dbt_compile(env)
93119
_copy_dbt_manifest()

data_pipelines_cli/cli_commands/create.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def _get_template_path(
4343

4444
def create(project_path: str, template_path: Optional[str]) -> None:
4545
"""
46-
Create a new project using a template
46+
Create a new project using a template.
4747
4848
:param project_path: Path to a directory to create
4949
:type project_path: str

data_pipelines_cli/cli_commands/deploy.py

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,22 @@
66
import yaml
77

88
from ..cli_constants import BUILD_DIR
9-
from ..cli_utils import echo_info, subprocess_run
9+
from ..cli_utils import echo_error, echo_info, subprocess_run
1010
from ..config_generation import read_dictionary_from_config_directory
1111
from ..data_structures import DockerArgs
12+
from ..docker_response_reader import DockerResponseReader
1213
from ..errors import (
1314
AirflowDagsPathKeyError,
1415
DataPipelinesError,
1516
DependencyNotInstalledError,
17+
DockerErrorResponseError,
1618
DockerNotInstalledError,
1719
)
1820
from ..filesystem_utils import LocalRemoteSync
1921

2022

2123
class DeployCommand:
22-
"""A class used to push and deploy the project to the remote machine"""
24+
"""A class used to push and deploy the project to the remote machine."""
2325

2426
docker_args: Optional[DockerArgs]
2527
"""Arguments required by the Docker to make a push to the repository.
@@ -45,17 +47,16 @@ def __init__(
4547
self.provider_kwargs_dict = provider_kwargs_dict or {}
4648

4749
try:
48-
self.blob_address_path = (
49-
dags_path
50-
or read_dictionary_from_config_directory(
51-
BUILD_DIR.joinpath("dag"), "base", "airflow.yml"
52-
)["dags_path"]
53-
)
50+
self.blob_address_path = dags_path or read_dictionary_from_config_directory(
51+
BUILD_DIR.joinpath("dag"),
52+
env,
53+
"airflow.yml",
54+
)["dags_path"]
5455
except KeyError as key_error:
5556
raise AirflowDagsPathKeyError from key_error
5657

5758
def deploy(self) -> None:
58-
"""Push and deploy the project to the remote machine
59+
"""Push and deploy the project to the remote machine.
5960
6061
:raises DependencyNotInstalledError: DataHub or Docker not installed
6162
:raises DataPipelinesError: Error while pushing Docker image
@@ -81,20 +82,23 @@ def _docker_push(self) -> None:
8182
echo_info("Pushing Docker image")
8283
docker_client = docker.from_env()
8384
docker_args = cast(DockerArgs, self.docker_args)
84-
for line in docker_client.images.push(
85-
repository=docker_args.repository,
86-
tag=docker_args.commit_sha,
87-
stream=True,
88-
decode=True,
89-
):
90-
click.echo(line)
91-
92-
if "error" in line:
93-
raise DataPipelinesError(
94-
"Error raised when pushing Docker image. Ensure that "
95-
"Docker image you try to push exists. Maybe try running "
96-
"'dp compile' first?"
85+
86+
try:
87+
DockerResponseReader(
88+
docker_client.images.push(
89+
repository=docker_args.repository,
90+
tag=docker_args.commit_sha,
91+
stream=True,
92+
decode=True,
9793
)
94+
).click_echo_ok_responses()
95+
except DockerErrorResponseError as err:
96+
echo_error(err.message)
97+
raise DataPipelinesError(
98+
"Error raised when pushing Docker image. Ensure that "
99+
"Docker image you try to push exists. Maybe try running "
100+
"'dp compile' first?"
101+
)
98102

99103
@staticmethod
100104
def _datahub_ingest() -> None:
@@ -125,7 +129,9 @@ def _sync_bucket(self) -> None:
125129
name="deploy",
126130
help="Push and deploy the project to the remote machine",
127131
)
128-
@click.option("--env", default="base", type=str, help="Name of the environment")
132+
@click.option(
133+
"--env", default="base", show_default=True, type=str, help="Name of the environment"
134+
)
129135
@click.option("--dags-path", required=False, help="Remote storage URI")
130136
@click.option(
131137
"--blob-args",

data_pipelines_cli/cli_commands/init.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def _download_global_config(config_path: str) -> DataPipelinesConfig:
2525

2626
def init(config_path: Optional[str]) -> None:
2727
"""
28-
Configure the tool for the first time
28+
Configure the tool for the first time.
2929
3030
:param config_path: URI of the repository with a template of the config file
3131
:type config_path: Optional[str]

0 commit comments

Comments
 (0)