lennybot 1.0.21__tar.gz → 1.0.26__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 (43) hide show
  1. {lennybot-1.0.21 → lennybot-1.0.26}/PKG-INFO +1 -1
  2. {lennybot-1.0.21 → lennybot-1.0.26}/requirements.txt +1 -1
  3. {lennybot-1.0.21 → lennybot-1.0.26}/setup.py +0 -1
  4. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/actions/iaction.py +3 -3
  5. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/check/docker_image_available.py +28 -9
  6. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/check/icheck.py +4 -4
  7. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/config/config.py +16 -3
  8. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/model/state.py +2 -0
  9. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/service/github.py +1 -1
  10. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/service/plan.py +14 -2
  11. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/service/source/isource.py +2 -2
  12. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot.egg-info/PKG-INFO +1 -1
  13. {lennybot-1.0.21 → lennybot-1.0.26}/test/test_docker_image_available.py +9 -3
  14. lennybot-1.0.26/version.txt +1 -0
  15. lennybot-1.0.21/version.txt +0 -1
  16. {lennybot-1.0.21 → lennybot-1.0.26}/LICENSE +0 -0
  17. {lennybot-1.0.21 → lennybot-1.0.26}/README.md +0 -0
  18. {lennybot-1.0.21 → lennybot-1.0.26}/pyproject.toml +0 -0
  19. {lennybot-1.0.21 → lennybot-1.0.26}/setup.cfg +0 -0
  20. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/__init__.py +0 -0
  21. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/__main__.py +0 -0
  22. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/actions/__init__.py +0 -0
  23. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/actions/download_resources.py +0 -0
  24. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/actions/remove_checksums.py +0 -0
  25. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/actions/update_dockerfile.py +0 -0
  26. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/actions/update_image_tag.py +0 -0
  27. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/actions/update_yaml.py +0 -0
  28. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/check/__init__.py +0 -0
  29. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/config/__init__.py +0 -0
  30. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/helper/__init__.py +0 -0
  31. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/lennybot.py +0 -0
  32. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/model/__init__.py +0 -0
  33. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/model/plan.py +0 -0
  34. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/service/__init__.py +0 -0
  35. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/service/apply.py +0 -0
  36. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/service/source/__init__.py +0 -0
  37. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/service/source/source_github.py +0 -0
  38. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot/service/source/source_github_query.py +0 -0
  39. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot.egg-info/SOURCES.txt +0 -0
  40. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot.egg-info/dependency_links.txt +0 -0
  41. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot.egg-info/entry_points.txt +0 -0
  42. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot.egg-info/requires.txt +0 -0
  43. {lennybot-1.0.21 → lennybot-1.0.26}/src/lennybot.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lennybot
3
- Version: 1.0.21
3
+ Version: 1.0.26
4
4
  Summary: Automatic Updates for Kustomize Resources
5
5
  Home-page: http://github.com/raynigon/lennybot
6
6
  Author: Simon Schneider
@@ -2,4 +2,4 @@ pyyaml
2
2
  yamlpath
3
3
  requests
4
4
  GitPython
5
- PyGithub
5
+ PyGithub
@@ -5,7 +5,6 @@ https://github.com/pypa/sampleproject
5
5
  """
6
6
 
7
7
  import pkg_resources
8
-
9
8
  # Always prefer setuptools over distutils
10
9
  from setuptools import find_packages, setup
11
10
 
@@ -1,14 +1,14 @@
1
1
  class IAction:
2
2
  @property
3
- def application(self) -> str: # pyright: ignore [reportGeneralTypeIssues]
3
+ def application(self) -> str: # pyright: ignore [reportGeneralTypeIssues, reportReturnType]
4
4
  pass
5
5
 
6
6
  @property
7
- def source_version(self) -> str: # pyright: ignore [reportGeneralTypeIssues]
7
+ def source_version(self) -> str: # pyright: ignore [reportGeneralTypeIssues, reportReturnType]
8
8
  pass
9
9
 
10
10
  @property
11
- def target_version(self) -> str: # pyright: ignore [reportGeneralTypeIssues]
11
+ def target_version(self) -> str: # pyright: ignore [reportGeneralTypeIssues, reportReturnType]
12
12
  pass
13
13
 
14
14
  def run(self):
@@ -103,7 +103,11 @@ class DockerImageAvailableCheck(ICheck):
103
103
  + image_tag
104
104
  )
105
105
  return DockerImage(match.group(4), match.group(5) + "/" + match.group(6), image_tag)
106
- return DockerImage(match.group(7), match.group(8) + "/" + match.group(9) + "/" + match.group(10), image_tag)
106
+ return DockerImage(
107
+ match.group(7),
108
+ match.group(8) + "/" + match.group(9) + "/" + match.group(10),
109
+ image_tag,
110
+ )
107
111
 
108
112
  def _authenticate_on_registry(self, registry: str, authentication_header: WwwAuthenticateHeader) -> str:
109
113
  params = {
@@ -118,8 +122,12 @@ class DockerImageAvailableCheck(ICheck):
118
122
 
119
123
  if registry in self._container_config.registries.keys():
120
124
  registry_data = self._container_config.registries[registry]
121
- password = registry_data.password
122
125
  username = registry_data.username
126
+ password = registry_data.password
127
+ if "<REDACTED>" in [username, password]:
128
+ logging.warning(
129
+ "Either username or password contain '<REDACTED>' and probably have not been overwritten"
130
+ )
123
131
  response = requests.get(url, auth=(username, password))
124
132
  else:
125
133
  logging.debug("Registry not found in config")
@@ -139,15 +147,23 @@ class DockerImageAvailableCheck(ICheck):
139
147
  return str(access_token)
140
148
 
141
149
  if response.status_code == 401:
142
- logging.error("Authentication failed:", response.status_code, response.headers)
150
+ logging.error(
151
+ "Authentication failed: %d with %s",
152
+ response.status_code,
153
+ response.headers,
154
+ )
143
155
  raise Exception("Error occurred: Unauthenticated: ", response.status_code)
144
156
 
145
157
  if response.status_code == 403:
146
- logging.error("Authorization failed:", response.status_code, response.headers)
158
+ logging.error(
159
+ "Authorization failed: %d with %s",
160
+ response.status_code,
161
+ response.headers,
162
+ )
147
163
  raise Exception("Error occurred: Unauthorization: ", response.status_code)
148
164
 
149
165
  if response.status_code == 404:
150
- logging.error("Nothing Found:", response.status_code, response.headers)
166
+ logging.error("Nothing Found: %d with %s", response.status_code, response.headers)
151
167
  raise Exception("Error occurred: Nothing Found: ", response.status_code)
152
168
 
153
169
  raise Exception("Unexpected Status Code", response.status_code)
@@ -176,11 +192,14 @@ class DockerImageAvailableCheck(ICheck):
176
192
 
177
193
  request_url = f"https://{image._registry}/v2/{image._name}/manifests/{image._tag}"
178
194
 
195
+ # depending on the registry it my helps adding the write accept header :)
196
+ # https://github.com/goharbor/harbor/issues/16075
197
+ headers = {
198
+ "Accept": "application/vnd.oci.image.index.v1+json, application/vnd.docker.distribution.manifest.list.v2+json",
199
+ }
179
200
  if access_token is not None:
180
- headers = {"Authorization": f"Bearer {access_token}"}
181
- response = requests.get(request_url, headers=headers)
182
- else:
183
- response = requests.get(request_url)
201
+ headers["Authorization"] = f"Bearer {access_token}"
202
+ response = requests.get(request_url, headers=headers)
184
203
 
185
204
  if response.status_code == 401 and access_token is None:
186
205
  registry = image._registry
@@ -1,15 +1,15 @@
1
1
  class ICheck:
2
2
  @property
3
- def application(self) -> str: # pyright: ignore [reportGeneralTypeIssues]
3
+ def application(self) -> str: # pyright: ignore [reportGeneralTypeIssues, reportReturnType]
4
4
  pass
5
5
 
6
6
  @property
7
- def source_version(self) -> str: # pyright: ignore [reportGeneralTypeIssues]
7
+ def source_version(self) -> str: # pyright: ignore [reportGeneralTypeIssues, reportReturnType]
8
8
  pass
9
9
 
10
10
  @property
11
- def target_version(self) -> str: # pyright: ignore [reportGeneralTypeIssues]
11
+ def target_version(self) -> str: # pyright: ignore [reportGeneralTypeIssues, reportReturnType]
12
12
  pass
13
13
 
14
- def check(self) -> bool: # pyright: ignore [reportGeneralTypeIssues]
14
+ def check(self) -> bool: # pyright: ignore [reportGeneralTypeIssues, reportReturnType]
15
15
  pass
@@ -26,7 +26,13 @@ CONFIGURATION_OPTIONS = {
26
26
  },
27
27
  "logging": {
28
28
  "type": "object",
29
- "properties": {"level": {"type": "string", "required": False, "attribute": "_logging_level"}},
29
+ "properties": {
30
+ "level": {
31
+ "type": "string",
32
+ "required": False,
33
+ "attribute": "_logging_level",
34
+ }
35
+ },
30
36
  },
31
37
  "container": {
32
38
  "type": "object",
@@ -56,7 +62,11 @@ CONFIGURATION_OPTIONS = {
56
62
  "attribute": "_source",
57
63
  "properties": {
58
64
  "type": {"type": "string", "required": True, "attribute": "_type"},
59
- "repository": {"type": "string", "required": True, "attribute": "_repository"},
65
+ "repository": {
66
+ "type": "string",
67
+ "required": True,
68
+ "attribute": "_repository",
69
+ },
60
70
  "regex": {"type": "string", "attribute": "_regex"},
61
71
  },
62
72
  },
@@ -259,7 +269,10 @@ class LennyBotConfig:
259
269
 
260
270
  def _configure_logging(self):
261
271
  logging_level = logging._nameToLevel.get(self._logging_level, logging.DEBUG)
262
- logging.basicConfig(level=logging_level, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s")
272
+ logging.basicConfig(
273
+ level=logging_level,
274
+ format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
275
+ )
263
276
  self._log = logging.getLogger(self.__class__.__name__)
264
277
  self._log.debug("Logging was configured")
265
278
 
@@ -13,6 +13,8 @@ class LennyBotState:
13
13
  self._hash = self._calculate_hash()
14
14
  with open(self._filename, encoding="utf-8") as file_ptr:
15
15
  self._data = yaml.safe_load(file_ptr)
16
+ if self._data is None:
17
+ self._data = {}
16
18
 
17
19
  def _init_file(self):
18
20
  if not os.path.exists(self._filename):
@@ -34,7 +34,7 @@ class GitHubService:
34
34
  if self._github is None:
35
35
  raise Exception("GitHub is not configured")
36
36
  repo = self._github.get_repo(self._config.github_pr.repository)
37
- new_pull = repo.create_pull(title, body, repo.default_branch, branch_name)
37
+ new_pull = repo.create_pull(repo.default_branch, branch_name, title=title, body=body)
38
38
  labels = self._get_or_create_labels(repo)
39
39
  new_pull.add_to_labels(*labels)
40
40
  pulls = self._find_own_pulls()
@@ -31,7 +31,13 @@ class LennyBotApplication:
31
31
  self._current_version = state.current_version(self._name)
32
32
  self._latest_version = self._source.latest_version()
33
33
  for config in self._config._checks:
34
- check = create_check(self.name, self._current_version, self._latest_version, config, self._global_config)
34
+ check = create_check(
35
+ self.name,
36
+ self._current_version,
37
+ self._latest_version,
38
+ config,
39
+ self._global_config,
40
+ )
35
41
  self._checks.append(check)
36
42
 
37
43
  def should_update(self) -> bool:
@@ -47,7 +53,13 @@ class LennyBotApplication:
47
53
 
48
54
  for check in self._checks:
49
55
  if not check.check():
50
- self._log.info("Check '%s' failed for application '%s'", check.__class__.__name__, self.name)
56
+ self._log.warning(
57
+ "Check '%s' failed for application '%s' with current version '%s' and latest version '%s'",
58
+ check.__class__.__name__,
59
+ self.name,
60
+ self._current_version,
61
+ self._latest_version,
62
+ )
51
63
  return False
52
64
  return True
53
65
 
@@ -1,7 +1,7 @@
1
1
  class ISource:
2
2
  @property
3
- def application(self) -> str: # pyright: ignore [reportGeneralTypeIssues]
3
+ def application(self) -> str: # pyright: ignore [reportGeneralTypeIssues, reportReturnType]
4
4
  pass
5
5
 
6
- def latest_version(self) -> str: # pyright: ignore [reportGeneralTypeIssues]
6
+ def latest_version(self) -> str: # pyright: ignore [reportGeneralTypeIssues, reportReturnType]
7
7
  pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lennybot
3
- Version: 1.0.21
3
+ Version: 1.0.26
4
4
  Summary: Automatic Updates for Kustomize Resources
5
5
  Home-page: http://github.com/raynigon/lennybot
6
6
  Author: Simon Schneider
@@ -54,7 +54,9 @@ class TestAuthenticateImage(unittest.TestCase):
54
54
  def test_authenticate_on_registry_returns_access_token(self):
55
55
  registry = LennyBotConfigContainerRegistry("hub.docker.io")
56
56
  header_value = WwwAuthenticateHeader(
57
- "https://docker-auth.elastic.co/auth", "repository:beats/filebeat:pull", "token-service"
57
+ "https://docker-auth.elastic.co/auth",
58
+ "repository:beats/filebeat:pull",
59
+ "token-service",
58
60
  )
59
61
  access_token = self.docker_image_check._authenticate_on_registry(registry.name, header_value)
60
62
  self.assertIsNotNone(access_token)
@@ -62,7 +64,9 @@ class TestAuthenticateImage(unittest.TestCase):
62
64
  def test_authenticate_without_credentials_in_config(self):
63
65
  self.config._image_pattern = "quay.io/argoproj/argocd:v{{version}}"
64
66
  header_value = WwwAuthenticateHeader(
65
- "https://quay.io/v2/auth", "repository:argoproj/argocd:pull", "token-service"
67
+ "https://quay.io/v2/auth",
68
+ "repository:argoproj/argocd:pull",
69
+ "token-service",
66
70
  )
67
71
  access_token = self.docker_image_check._authenticate_on_registry("", header_value)
68
72
  self.assertIsNotNone(access_token)
@@ -74,7 +78,9 @@ class TestAuthenticateImage(unittest.TestCase):
74
78
  registry._password = "1234"
75
79
  self.container_config._registries["ghcr.io"] = registry
76
80
  header_value = WwwAuthenticateHeader(
77
- "https://ghcr.io/v2/auth", "repository:brose-ebike/postgres-operator:pull", "token-service"
81
+ "https://ghcr.io/v2/auth",
82
+ "repository:brose-ebike/postgres-operator:pull",
83
+ "token-service",
78
84
  )
79
85
 
80
86
  with self.assertRaises(Exception) as context:
@@ -0,0 +1 @@
1
+ 1.0.26
@@ -1 +0,0 @@
1
- 1.0.21
File without changes
File without changes
File without changes
File without changes