dbt-copilot-python 0.1.4__tar.gz → 0.1.5.dev2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dbt-copilot-python
3
- Version: 0.1.4
3
+ Version: 0.1.5.dev2
4
4
  Summary: Helper functions to run Django and Flask applications in AWS Copilot/ECS.
5
5
  Author: Department for Business and Trade Platform Team
6
6
  Author-email: sre-team@digital.trade.gov.uk
@@ -9,11 +9,16 @@ Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Programming Language :: Python :: 3.9
10
10
  Classifier: Programming Language :: Python :: 3.10
11
11
  Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Requires-Dist: celery (>=5.3.6,<6.0.0)
12
14
  Requires-Dist: opentelemetry-distro (==0.43b0)
13
15
  Requires-Dist: opentelemetry-exporter-otlp (==1.22.0)
14
16
  Requires-Dist: opentelemetry-instrumentation-wsgi (==0.43b0)
15
17
  Requires-Dist: opentelemetry-propagator-aws-xray (>=1.0.1,<2.0.0)
16
18
  Requires-Dist: opentelemetry-sdk-extension-aws (>=2.0.1,<3.0.0)
19
+ Requires-Dist: pytest-celery (>=0.0.0,<0.0.1)
20
+ Requires-Dist: pytest-mock (>=3.12.0,<4.0.0)
21
+ Requires-Dist: redis (>=5.0.1,<6.0.0)
17
22
  Requires-Dist: requests (>=2.31.0,<3.0.0)
18
23
  Description-Content-Type: text/markdown
19
24
 
@@ -27,19 +32,17 @@ A set of utility functions for running Django & Flask apps in AWS ECS via AWS Co
27
32
 
28
33
  ### Installation
29
34
 
30
- ```
35
+ ```shell
31
36
  pip install dbt-copilot-python
32
37
  ```
33
38
 
34
39
  ### Usage
35
40
 
36
- In `settings.py`...
37
-
38
- #### ALLOWED_HOSTS
41
+ #### `ALLOWED_HOSTS` setting
39
42
 
40
- Add the ECS container IP to `ALLOWED_HOSTS` so that the Application Load Balancer (ALB) healthcheck will succeed:
43
+ Add the ECS container IP to `ALLOWED_HOSTS` setting so that the Application Load Balancer (ALB) healthcheck will succeed:
41
44
 
42
- ```
45
+ ```python
43
46
  from dbt_copilot_python.network import setup_allowed_hosts
44
47
 
45
48
  ALLOWED_HOSTS = [...]
@@ -47,7 +50,42 @@ ALLOWED_HOSTS = [...]
47
50
  ALLOWED_HOSTS = setup_allowed_hosts(ALLOWED_HOSTS)
48
51
  ```
49
52
 
50
- #### DATABASES
53
+ #### Celery health check
54
+
55
+ Add the health check in your application's Celery config file...
56
+
57
+ ```python
58
+ from dbt_copilot_python.celery_health_check import healthcheck
59
+
60
+ celery_app = Celery("application_name")
61
+ ...
62
+
63
+ celery_app = healthcheck.setup(celery_app)
64
+ ```
65
+
66
+ Add the health check to the Celery worker service in `docker-compose.yml`...
67
+
68
+ ```yaml
69
+ healthcheck:
70
+ test: [ "CMD-SHELL", "python -m dbt_copilot_python.celery_health_check.healthcheck" ]
71
+ interval: 10s
72
+ timeout: 5s
73
+ retries: 2
74
+ start_period: 5s
75
+ ```
76
+
77
+ In your `*-deploy` codebase, add the health check to the Celery worker service in `copilot/celery-worker/manifest.yml`...
78
+
79
+ ```yaml
80
+ healthcheck:
81
+ command: [ "CMD-SHELL", "launcher bash -c 'python -m dbt_copilot_python.celery_health_check.healthcheck'" ]
82
+ interval: 10s
83
+ timeout: 5s
84
+ retries: 2
85
+ start_period: 10s
86
+ ```
87
+
88
+ #### `DATABASES` setting
51
89
 
52
90
  To configure the `DATABASES` setting from an RDS JSON object stored in AWS Secrets Manager, there are two options.
53
91
 
@@ -55,7 +93,7 @@ To configure the `DATABASES` setting from an RDS JSON object stored in AWS Secre
55
93
 
56
94
  Note: This is dependent on the [`dj-database-url`](https://pypi.org/project/dj-database-url/) package which can be installed via `pip install dj-database-url`.
57
95
 
58
- ```
96
+ ```python
59
97
  import dj_database_url
60
98
 
61
99
  from dbt_copilot_python.database import database_url_from_env
@@ -69,7 +107,7 @@ To configure the `DATABASES` setting from an RDS JSON object stored in AWS Secre
69
107
 
70
108
  2. Configure the `DATABASES` setting to use a dictionary containing the settings:
71
109
 
72
- ```
110
+ ```python
73
111
  from dbt-copilot-python.database import database_from_env
74
112
 
75
113
  DATABASES = database_from_env("DATABASE_ENV_VAR_KEY")
@@ -83,13 +121,13 @@ To configure the `DATABASES` setting from an RDS JSON object stored in AWS Secre
83
121
 
84
122
  ### Install dependencies & pre-commit hooks
85
123
 
86
- ```
124
+ ```shell
87
125
  poetry install && poetry run pre-commit install
88
126
  ```
89
127
 
90
128
  ### Run the tests
91
129
 
92
- ```
130
+ ```shell
93
131
  poetry run pytest
94
132
  ```
95
133
 
@@ -104,7 +142,7 @@ To publish the Python package `dbt-copilot-python`, you will need an API token.
104
142
 
105
143
  Update the version, as the same version cannot be published to PyPi.
106
144
 
107
- ```
145
+ ```shell
108
146
  poetry version patch
109
147
  ```
110
148
 
@@ -112,7 +150,7 @@ More options for the `version` command can be found in the [Poetry documentation
112
150
 
113
151
  Build the Python package.
114
152
 
115
- ```
153
+ ```shell
116
154
  poetry build
117
155
  ```
118
156
 
@@ -120,7 +158,7 @@ Publish the Python package.
120
158
 
121
159
  _Note: Make sure your Pull Request (PR) is approved and contains the version upgrade in `pyproject.toml` before publishing the package._
122
160
 
123
- ```
161
+ ```shell
124
162
  poetry publish
125
163
  ```
126
164
 
@@ -8,19 +8,17 @@ A set of utility functions for running Django & Flask apps in AWS ECS via AWS Co
8
8
 
9
9
  ### Installation
10
10
 
11
- ```
11
+ ```shell
12
12
  pip install dbt-copilot-python
13
13
  ```
14
14
 
15
15
  ### Usage
16
16
 
17
- In `settings.py`...
18
-
19
- #### ALLOWED_HOSTS
17
+ #### `ALLOWED_HOSTS` setting
20
18
 
21
- Add the ECS container IP to `ALLOWED_HOSTS` so that the Application Load Balancer (ALB) healthcheck will succeed:
19
+ Add the ECS container IP to `ALLOWED_HOSTS` setting so that the Application Load Balancer (ALB) healthcheck will succeed:
22
20
 
23
- ```
21
+ ```python
24
22
  from dbt_copilot_python.network import setup_allowed_hosts
25
23
 
26
24
  ALLOWED_HOSTS = [...]
@@ -28,7 +26,42 @@ ALLOWED_HOSTS = [...]
28
26
  ALLOWED_HOSTS = setup_allowed_hosts(ALLOWED_HOSTS)
29
27
  ```
30
28
 
31
- #### DATABASES
29
+ #### Celery health check
30
+
31
+ Add the health check in your application's Celery config file...
32
+
33
+ ```python
34
+ from dbt_copilot_python.celery_health_check import healthcheck
35
+
36
+ celery_app = Celery("application_name")
37
+ ...
38
+
39
+ celery_app = healthcheck.setup(celery_app)
40
+ ```
41
+
42
+ Add the health check to the Celery worker service in `docker-compose.yml`...
43
+
44
+ ```yaml
45
+ healthcheck:
46
+ test: [ "CMD-SHELL", "python -m dbt_copilot_python.celery_health_check.healthcheck" ]
47
+ interval: 10s
48
+ timeout: 5s
49
+ retries: 2
50
+ start_period: 5s
51
+ ```
52
+
53
+ In your `*-deploy` codebase, add the health check to the Celery worker service in `copilot/celery-worker/manifest.yml`...
54
+
55
+ ```yaml
56
+ healthcheck:
57
+ command: [ "CMD-SHELL", "launcher bash -c 'python -m dbt_copilot_python.celery_health_check.healthcheck'" ]
58
+ interval: 10s
59
+ timeout: 5s
60
+ retries: 2
61
+ start_period: 10s
62
+ ```
63
+
64
+ #### `DATABASES` setting
32
65
 
33
66
  To configure the `DATABASES` setting from an RDS JSON object stored in AWS Secrets Manager, there are two options.
34
67
 
@@ -36,7 +69,7 @@ To configure the `DATABASES` setting from an RDS JSON object stored in AWS Secre
36
69
 
37
70
  Note: This is dependent on the [`dj-database-url`](https://pypi.org/project/dj-database-url/) package which can be installed via `pip install dj-database-url`.
38
71
 
39
- ```
72
+ ```python
40
73
  import dj_database_url
41
74
 
42
75
  from dbt_copilot_python.database import database_url_from_env
@@ -50,7 +83,7 @@ To configure the `DATABASES` setting from an RDS JSON object stored in AWS Secre
50
83
 
51
84
  2. Configure the `DATABASES` setting to use a dictionary containing the settings:
52
85
 
53
- ```
86
+ ```python
54
87
  from dbt-copilot-python.database import database_from_env
55
88
 
56
89
  DATABASES = database_from_env("DATABASE_ENV_VAR_KEY")
@@ -64,13 +97,13 @@ To configure the `DATABASES` setting from an RDS JSON object stored in AWS Secre
64
97
 
65
98
  ### Install dependencies & pre-commit hooks
66
99
 
67
- ```
100
+ ```shell
68
101
  poetry install && poetry run pre-commit install
69
102
  ```
70
103
 
71
104
  ### Run the tests
72
105
 
73
- ```
106
+ ```shell
74
107
  poetry run pytest
75
108
  ```
76
109
 
@@ -85,7 +118,7 @@ To publish the Python package `dbt-copilot-python`, you will need an API token.
85
118
 
86
119
  Update the version, as the same version cannot be published to PyPi.
87
120
 
88
- ```
121
+ ```shell
89
122
  poetry version patch
90
123
  ```
91
124
 
@@ -93,7 +126,7 @@ More options for the `version` command can be found in the [Poetry documentation
93
126
 
94
127
  Build the Python package.
95
128
 
96
- ```
129
+ ```shell
97
130
  poetry build
98
131
  ```
99
132
 
@@ -101,7 +134,7 @@ Publish the Python package.
101
134
 
102
135
  _Note: Make sure your Pull Request (PR) is approved and contains the version upgrade in `pyproject.toml` before publishing the package._
103
136
 
104
- ```
137
+ ```shell
105
138
  poetry publish
106
139
  ```
107
140
 
@@ -0,0 +1,5 @@
1
+ import tempfile
2
+ from pathlib import Path
3
+
4
+ READINESS_FILE = Path(f"{tempfile.gettempdir()}/celery_ready")
5
+ HEARTBEAT_FILE = Path(f"{tempfile.gettempdir()}/celery_worker_heartbeat")
@@ -0,0 +1,58 @@
1
+ # See https://medium.com/ambient-innovation/health-checks-for-celery-in-kubernetes-cf3274a3e106
2
+
3
+ import sys
4
+ from datetime import UTC
5
+ from datetime import datetime
6
+
7
+ from celery import signals
8
+
9
+ from .const import HEARTBEAT_FILE
10
+ from .const import READINESS_FILE
11
+ from .heartbeat import HeartBeat
12
+
13
+
14
+ def on_worker_ready(**_):
15
+ READINESS_FILE.touch()
16
+
17
+
18
+ def on_worker_shutdown(**_):
19
+ READINESS_FILE.unlink(missing_ok=True)
20
+
21
+
22
+ def setup(celery_app=None):
23
+ signals.worker_ready.connect(on_worker_ready)
24
+
25
+ signals.worker_shutdown.connect(on_worker_shutdown)
26
+
27
+ celery_app.steps["worker"].add(HeartBeat)
28
+ return celery_app
29
+
30
+
31
+ def check_health():
32
+ if not READINESS_FILE.is_file():
33
+ print("Healthcheck: Celery readiness file NOT found.")
34
+ sys.exit(1)
35
+
36
+ if not HEARTBEAT_FILE.is_file():
37
+ print("Healthcheck: Celery heartbeat file NOT found.")
38
+ sys.exit(1)
39
+
40
+ heartbeat_timestamp = float(HEARTBEAT_FILE.read_text())
41
+ current_timestamp = datetime.now(UTC).timestamp()
42
+ time_diff = current_timestamp - heartbeat_timestamp
43
+ if time_diff > 60:
44
+ print(
45
+ "Healthcheck: Celery Worker heartbeat file timestamp "
46
+ + "DOES NOT match the given constraint."
47
+ )
48
+ sys.exit(1)
49
+
50
+ print(
51
+ "Healthcheck: Celery Worker heartbeat file found and timestamp "
52
+ + "matches the given constraint."
53
+ )
54
+ sys.exit(0)
55
+
56
+
57
+ if __name__ == "__main__":
58
+ check_health()
@@ -0,0 +1,29 @@
1
+ from datetime import UTC
2
+ from datetime import datetime
3
+
4
+ from celery import bootsteps
5
+
6
+ from .const import HEARTBEAT_FILE
7
+
8
+
9
+ class HeartBeat(bootsteps.StartStopStep):
10
+ requires = {"celery.worker.components:Timer"}
11
+
12
+ def __init__(self, parent, **kwargs):
13
+ super().__init__(parent, **kwargs)
14
+ self.requests = []
15
+ self.tref = None
16
+
17
+ def start(self, worker):
18
+ self.tref = worker.timer.call_repeatedly(
19
+ 1.0,
20
+ self.update_heartbeat_file,
21
+ (worker,),
22
+ priority=10,
23
+ )
24
+
25
+ def stop(self, worker):
26
+ HEARTBEAT_FILE.unlink(missing_ok=True)
27
+
28
+ def update_heartbeat_file(self, worker):
29
+ HEARTBEAT_FILE.write_text(str(datetime.timestamp(datetime.now(UTC))))
@@ -3,7 +3,7 @@ line-length = 100
3
3
 
4
4
  [tool.poetry]
5
5
  name = "dbt-copilot-python"
6
- version = "0.1.4"
6
+ version = "0.1.5-dev2"
7
7
  description = "Helper functions to run Django and Flask applications in AWS Copilot/ECS."
8
8
  authors = ["Department for Business and Trade Platform Team <sre-team@digital.trade.gov.uk>"]
9
9
  readme = "README.md"
@@ -11,17 +11,21 @@ packages = [{ include = "dbt_copilot_python" }]
11
11
 
12
12
  [tool.poetry.dependencies]
13
13
  python = "^3.9"
14
- requests = "^2.31.0"
14
+ celery = "^5.3.6"
15
15
  opentelemetry-distro = "0.43b0"
16
16
  opentelemetry-exporter-otlp = "1.22.0"
17
17
  opentelemetry-instrumentation-wsgi = "0.43b0"
18
18
  opentelemetry-propagator-aws-xray = "^1.0.1"
19
19
  opentelemetry-sdk-extension-aws = "^2.0.1"
20
+ requests = "^2.31.0"
21
+ pytest-celery = "^0.0.0"
22
+ redis = "^5.0.1"
23
+ pytest-mock = "^3.12.0"
20
24
 
21
25
  [tool.poetry.group.dev.dependencies]
26
+ pre-commit = "^3.3.3"
22
27
  pytest = "^7.3.2"
23
28
  requests-mock = "^1.11.0"
24
- pre-commit = "^3.3.3"
25
29
  tox = "^4.6.3"
26
30
 
27
31
  [build-system]