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