kubernetes-watch 0.1.10__tar.gz → 0.1.12__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.
Files changed (36) hide show
  1. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/PKG-INFO +2 -2
  2. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/clusters/kube.py +74 -3
  3. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/providers/aws.py +46 -0
  4. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/pyproject.toml +2 -2
  5. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/LICENSE +0 -0
  6. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/README.md +0 -0
  7. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/__init__.py +0 -0
  8. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/enums/__init__.py +0 -0
  9. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/enums/kube.py +0 -0
  10. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/enums/logic.py +0 -0
  11. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/enums/providers.py +0 -0
  12. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/enums/workflow.py +0 -0
  13. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/models/__init__.py +0 -0
  14. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/models/common.py +0 -0
  15. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/models/workflow.py +0 -0
  16. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/__init__.py +0 -0
  17. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/clusters/__init__.py +0 -0
  18. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/database/__init__.py +0 -0
  19. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/database/model.py +0 -0
  20. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/database/postgre.py +0 -0
  21. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/logic/actions.py +0 -0
  22. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/logic/checks.py +0 -0
  23. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/logic/load.py +0 -0
  24. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/logic/merge.py +0 -0
  25. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/logic/scheduler.py +0 -0
  26. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/logic/trasnform.py +0 -0
  27. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/mock/__init__.py +0 -0
  28. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/mock/mock_generator.py +0 -0
  29. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/providers/__init__.py +0 -0
  30. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/providers/git.py +0 -0
  31. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/providers/github.py +0 -0
  32. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/modules/providers/vault.py +0 -0
  33. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/standalone/metarecogen/ckan_to_gn.py +0 -0
  34. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/watch/__init__.py +0 -0
  35. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/watch/helpers.py +0 -0
  36. {kubernetes_watch-0.1.10 → kubernetes_watch-0.1.12}/kube_watch/watch/workflow.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kubernetes-watch
3
- Version: 0.1.10
3
+ Version: 0.1.12
4
4
  Summary:
5
5
  Author: bmotevalli
6
6
  Author-email: b.motevalli@gmail.com
@@ -15,7 +15,7 @@ Requires-Dist: boto3 (>=1.34.68,<2.0.0)
15
15
  Requires-Dist: humps (>=0.2.2,<0.3.0)
16
16
  Requires-Dist: hvac (>=2.1.0,<3.0.0)
17
17
  Requires-Dist: kubernetes (>=29.0.0,<30.0.0)
18
- Requires-Dist: prefect (>=3.4.17,<4.0.0)
18
+ Requires-Dist: prefect (==3.4.18)
19
19
  Requires-Dist: psycopg2 (>=2.9.10,<3.0.0)
20
20
  Requires-Dist: pydantic (>=2.11.7,<3.0.0)
21
21
  Requires-Dist: requests (>=2.32.3,<3.0.0)
@@ -1,7 +1,6 @@
1
1
  from prefect import get_run_logger
2
2
  from typing import List
3
- from kubernetes import config
4
- from kubernetes import client
3
+ from kubernetes import config, client, utils
5
4
  from kubernetes.client.rest import ApiException
6
5
  import base64
7
6
  import datetime
@@ -183,4 +182,76 @@ def has_mismatch_image_digest(repo_digest, label_selector, namespace):
183
182
  logger.info("Images are in-sync.")
184
183
  logger.info(f"Repo digest: {repo_digest}")
185
184
  logger.info(f"Curr digest: {current_image_id.split('@')[-1]}")
186
- return False
185
+ return False
186
+
187
+
188
+ def update_deployment_image_if_needed(namespace, deployment_name, container_name, new_tag):
189
+ """
190
+ Updates the deployment's container image tag only if it differs from the current one.
191
+ The repository URI is extracted automatically from the current image reference.
192
+
193
+ Args:
194
+ namespace: Kubernetes namespace where the deployment resides.
195
+ deployment_name: Name of the deployment to patch.
196
+ container_name: Name of the container inside the deployment.
197
+ new_tag: The new image tag to set, e.g. 'v1.2.3'
198
+
199
+ Returns:
200
+ True if the image was updated and rollout triggered, False otherwise.
201
+ """
202
+ try:
203
+ # Load kube config (works both in-cluster and local)
204
+ try:
205
+ config.load_incluster_config()
206
+ except config.ConfigException:
207
+ config.load_kube_config()
208
+
209
+ apps_v1 = client.AppsV1Api()
210
+
211
+ # Read the current deployment
212
+ deployment = apps_v1.read_namespaced_deployment(deployment_name, namespace)
213
+
214
+ # Find the container we want to update
215
+ containers = deployment.spec.template.spec.containers
216
+ target_container = next((c for c in containers if c.name == container_name), None)
217
+ if not target_container:
218
+ logger.error(f"Container '{container_name}' not found in deployment '{deployment_name}'.")
219
+ return False
220
+
221
+ current_image = target_container.image
222
+ if ':' in current_image:
223
+ repo_uri, current_tag = current_image.rsplit(':', 1)
224
+ else:
225
+ repo_uri, current_tag = current_image, "latest"
226
+
227
+ if current_tag == new_tag:
228
+ logger.info(f"No update needed. Deployment '{deployment_name}' already using tag '{new_tag}'.")
229
+ return False
230
+
231
+ # Build the new image reference using same repo
232
+ new_image = f"{repo_uri}:{new_tag}"
233
+ patch = {
234
+ "spec": {
235
+ "template": {
236
+ "spec": {
237
+ "containers": [
238
+ {"name": container_name, "image": new_image}
239
+ ]
240
+ }
241
+ }
242
+ }
243
+ }
244
+
245
+ logger.info(f"Updating '{deployment_name}' from '{current_image}' to '{new_image}'")
246
+ apps_v1.patch_namespaced_deployment(
247
+ name=deployment_name,
248
+ namespace=namespace,
249
+ body=patch
250
+ )
251
+
252
+ logger.info(f"Deployment '{deployment_name}' successfully updated to {new_image}")
253
+ return True
254
+
255
+ except Exception as e:
256
+ logger.error(f"Failed to update deployment '{deployment_name}': {e}")
257
+ return False
@@ -2,7 +2,9 @@
2
2
  # This class is deprecated. Please refer to aws.py
3
3
  #========================================================================
4
4
  import json
5
+ import re
5
6
  import base64
7
+ from packaging import version
6
8
  from datetime import datetime , timezone, timedelta
7
9
  import boto3
8
10
  from botocore.exceptions import ClientError
@@ -73,6 +75,50 @@ def task_get_latest_image_digest(session, resource, region, repository_name, tag
73
75
 
74
76
  raise ValueError('Unknown resource')
75
77
 
78
+
79
+ def task_get_highest_version_tag(session, resource, region, repository_name, tag_pattern=r"^v?(?P<version>\d+\.\d+\.\d+([-+][0-9A-Za-z.-]+)?)$"):
80
+ """
81
+ Fetches the highest versioned tag from an ECR repository, similar to FluxCD's semver filter.
82
+
83
+ Args:
84
+ session: boto3 session
85
+ resource: AwsResources enum
86
+ region: AWS region
87
+ repository_name: Name of the ECR repository
88
+ tag_pattern: Regex pattern to extract version component (default: semver)
89
+
90
+ Returns:
91
+ The highest matching tag or None if not found.
92
+ """
93
+ if resource == AwsResources.ECR:
94
+ ecr_client = session.client('ecr', region_name=region)
95
+ try:
96
+ pattern = re.compile(tag_pattern)
97
+ paginator = ecr_client.get_paginator('describe_images')
98
+ matched_tags = []
99
+
100
+ for page in paginator.paginate(repositoryName=repository_name, filter={'tagStatus': 'TAGGED'}):
101
+ for image in page.get('imageDetails', []):
102
+ for tag in image.get('imageTags', []):
103
+ match = pattern.match(tag)
104
+ if match:
105
+ ver_str = match.group('version')
106
+ matched_tags.append((tag, version.parse(ver_str)))
107
+
108
+ if not matched_tags:
109
+ logger.info(f"No tags matching pattern '{tag_pattern}' found in repository {repository_name}.")
110
+ return None
111
+
112
+ # Sort by semantic version and pick the highest
113
+ highest_tag, _ = max(matched_tags, key=lambda t: t[1])
114
+ return highest_tag
115
+
116
+ except Exception as e:
117
+ logger.error(f"Error fetching highest version tag from {repository_name}: {e}")
118
+ return None
119
+
120
+ raise ValueError('Unknown resource')
121
+
76
122
  #========================================================================================
77
123
  # IAM Cred update
78
124
  #========================================================================================
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "kubernetes-watch"
3
- version = "0.1.10"
3
+ version = "0.1.12"
4
4
  description = ""
5
5
  authors = ["bmotevalli <b.motevalli@gmail.com>"]
6
6
  packages = [{include = "kube_watch"}]
@@ -8,7 +8,7 @@ readme = "README.md"
8
8
 
9
9
  [tool.poetry.dependencies]
10
10
  python = ">=3.10,<3.14"
11
- prefect = "^3.4.17"
11
+ prefect = "3.4.18"
12
12
  boto3 = "^1.34.68"
13
13
  hvac = "^2.1.0"
14
14
  humps = "^0.2.2"