seto 3.2.0__tar.gz → 3.3.0__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 (28) hide show
  1. {seto-3.2.0 → seto-3.3.0}/PKG-INFO +1 -1
  2. {seto-3.2.0 → seto-3.3.0}/pyproject.toml +2 -1
  3. {seto-3.2.0 → seto-3.3.0}/seto/__main__.py +3 -0
  4. {seto-3.2.0 → seto-3.3.0}/seto/commands/config.py +4 -3
  5. {seto-3.2.0 → seto-3.3.0}/seto/commands/deploy.py +25 -21
  6. {seto-3.2.0 → seto-3.3.0}/seto/core/command.py +2 -1
  7. {seto-3.2.0 → seto-3.3.0}/seto/core/parser.py +9 -7
  8. {seto-3.2.0 → seto-3.3.0}/LICENSE +0 -0
  9. {seto-3.2.0 → seto-3.3.0}/LICENSE_HEADER.txt +0 -0
  10. {seto-3.2.0 → seto-3.3.0}/README.md +0 -0
  11. {seto-3.2.0 → seto-3.3.0}/seto/__init__.py +0 -0
  12. {seto-3.2.0 → seto-3.3.0}/seto/commands/down.py +0 -0
  13. {seto-3.2.0 → seto-3.3.0}/seto/commands/mount.py +0 -0
  14. {seto-3.2.0 → seto-3.3.0}/seto/commands/setup.py +0 -0
  15. {seto-3.2.0 → seto-3.3.0}/seto/commands/umount.py +0 -0
  16. {seto-3.2.0 → seto-3.3.0}/seto/commands/volumes.py +0 -0
  17. {seto-3.2.0 → seto-3.3.0}/seto/core/dns.py +0 -0
  18. {seto-3.2.0 → seto-3.3.0}/seto/core/docker.py +0 -0
  19. {seto-3.2.0 → seto-3.3.0}/seto/core/driver.py +0 -0
  20. {seto-3.2.0 → seto-3.3.0}/seto/core/network.py +0 -0
  21. {seto-3.2.0 → seto-3.3.0}/seto/core/permissions.py +0 -0
  22. {seto-3.2.0 → seto-3.3.0}/seto/core/shell.py +0 -0
  23. {seto-3.2.0 → seto-3.3.0}/seto/core/swarm.py +0 -0
  24. {seto-3.2.0 → seto-3.3.0}/seto/core/traefik.py +0 -0
  25. {seto-3.2.0 → seto-3.3.0}/seto/core/volume.py +0 -0
  26. {seto-3.2.0 → seto-3.3.0}/seto/drivers/nfs.py +0 -0
  27. {seto-3.2.0 → seto-3.3.0}/seto/shells/local.py +0 -0
  28. {seto-3.2.0 → seto-3.3.0}/seto/shells/remote.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: seto
3
- Version: 3.2.0
3
+ Version: 3.3.0
4
4
  Summary: A Docker Swarm Deployment Manager
5
5
  License: Apache 2.0
6
6
  Keywords: docker,swarm,manager
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "seto"
7
- version = "3.2.0"
7
+ version = "3.3.0"
8
8
  description = "A Docker Swarm Deployment Manager"
9
9
  keywords = ["docker", "swarm", "manager"]
10
10
  authors = ["Sébastien Demanou <demsking@gmail.com>"]
@@ -33,6 +33,7 @@ pyyaml = "^6.0.1"
33
33
  docker = "^7.1.0"
34
34
 
35
35
  [tool.poetry.group.dev.dependencies]
36
+ classify-imports = "^4.2.0"
36
37
 
37
38
  [tool.pytest.ini_options]
38
39
  # Function starting with the following pattern are considered for test cases.
@@ -194,6 +194,9 @@ def main() -> None:
194
194
  'deploy', description='Deploy a new stack or update an existing stack'
195
195
  )
196
196
  deploy_parser.set_defaults(func=execute_deploy_command)
197
+ deploy_parser.add_argument(
198
+ '--image-prefix', default='', help='Image namespace prefix to added to internal images'
199
+ )
197
200
 
198
201
  #
199
202
  # Down command
@@ -51,8 +51,8 @@ def resolve(
51
51
  }
52
52
 
53
53
  def parse(resolved_compose_data: dict, volumes: list[Volume]):
54
- placement_hostname = resolved_compose_data.get('x-placement-hostname', None)
55
- placement = resolved_compose_data.get('x-placement', None)
54
+ placement_hostname: str | None = resolved_compose_data.get('x-placement-hostname', None)
55
+ placement: str | None = resolved_compose_data.get('x-placement', None)
56
56
  networks_ = resolved_compose_data.get('networks', {})
57
57
  services = resolved_compose_data.get('services', {})
58
58
  volumes = resolved_compose_data.get('volumes', {})
@@ -72,10 +72,11 @@ def resolve(
72
72
  raise ValueError('Missing required x-placement or x-placement-hostname field')
73
73
 
74
74
  if execute:
75
- execute(resolved_compose_data, placement_hostname or placement)
75
+ execute(resolved_compose_data, placement_hostname or placement or '')
76
76
 
77
77
  parse_services(
78
78
  driver=driver,
79
+ image_prefix=args.image_prefix,
79
80
  stack=args.stack or args.project,
80
81
  execute=parse,
81
82
  inject=inject,
@@ -110,7 +110,9 @@ def parse_compose_config(
110
110
  published_port = random.randint(53100, 64200)
111
111
 
112
112
  if not service_traefik_port:
113
- print(f'WARN: Service "{service_name}" has no defined port. Skipped from Traefik HTTP Provider')
113
+ print(
114
+ f'WARN: Service "{service_name}" has no defined port. Skipped from Traefik HTTP Provider'
115
+ )
114
116
  continue
115
117
 
116
118
  service_ports.append(f'{published_port}:{service_traefik_port}')
@@ -184,6 +186,7 @@ def deploy_seto_stack(args, driver: Driver, replica: list[Setting]) -> None:
184
186
  # Resolving compose local volumes
185
187
  resolved_compose_data, volumes = resolve_compose_file(
186
188
  driver=driver,
189
+ image_prefix=args.image_prefix,
187
190
  compose_data=internal_stack,
188
191
  inject=True,
189
192
  )
@@ -239,30 +242,31 @@ def execute_deploy_command(args, driver: Driver) -> None:
239
242
  },
240
243
  }
241
244
 
242
- register_command = ' && '.join([
243
- f'echo "Registering service {driver.stack_id}..."',
244
- f'curl -s -X POST http://{HTTP_PROVIDER_SERVICENAME}:6116/api/config/{driver.stack_id} -H "Content-Type: application/json" -d @{traefik_http_provider_target} > /dev/nul',
245
- ])
246
-
247
- entrypoint = ' && '.join([
248
- # Log the start of the initial endpoint call
249
- 'echo "Starting initial call to the provider endpoint..."',
250
-
251
- # Call the POST endpoint at startup
252
- register_command,
253
-
254
- # Log the end of the initial endpoint call
255
- 'echo "Initial call to the provider endpoint completed. Running cron job..."',
256
-
257
- # Set up the cron job
258
- f'echo "*/1 * * * * {register_command}" | crontab -',
245
+ register_command = ' && '.join(
246
+ [
247
+ f'echo "Registering service {driver.stack_id}..."',
248
+ f'curl -s -X POST http://{HTTP_PROVIDER_SERVICENAME}:6116/api/config/{driver.stack_id} -H "Content-Type: application/json" -d @{traefik_http_provider_target} > /dev/nul',
249
+ ]
250
+ )
259
251
 
260
- # Start the cron service
261
- 'crond -f',
262
- ])
252
+ entrypoint = ' && '.join(
253
+ [
254
+ # Log the start of the initial endpoint call
255
+ 'echo "Starting initial call to the provider endpoint..."',
256
+ # Call the POST endpoint at startup
257
+ register_command,
258
+ # Log the end of the initial endpoint call
259
+ 'echo "Initial call to the provider endpoint completed. Running cron job..."',
260
+ # Set up the cron job
261
+ f'echo "*/1 * * * * {register_command}" | crontab -',
262
+ # Start the cron service
263
+ 'crond -f',
264
+ ]
265
+ )
263
266
 
264
267
  seto_agent_compose_data, _ = resolve_compose_file(
265
268
  driver=driver,
269
+ image_prefix=args.image_prefix,
266
270
  compose_data={
267
271
  'services': {
268
272
  'seto_agent': {
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Sébastien Demanou. All Rights Reserved.
1
+ # Copyright 2024-2025 Sébastien Demanou. All Rights Reserved.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@ def parse_volumes_args(args, driver: Driver) -> list[Volume]:
24
24
  driver=driver,
25
25
  stack=args.stack or args.project,
26
26
  execute=lambda resolved_compose_data, volumes: all_volumes.extend(volumes),
27
+ image_prefix=args.image_prefix,
27
28
  )
28
29
 
29
30
  return all_volumes
@@ -56,10 +56,7 @@ def parse_volume_entry(entry: str, default_mode='rw') -> tuple[str, str, str]:
56
56
 
57
57
 
58
58
  def parse_local_volumes(
59
- stack: str,
60
- *,
61
- service_name: str,
62
- service: Service,
59
+ stack: str, *, service_name: str, service: Service, image_prefix: str
63
60
  ) -> None:
64
61
  local_volumes = []
65
62
 
@@ -89,7 +86,7 @@ def parse_local_volumes(
89
86
  service_dockerfile = '\n'.join(service_dockerfile_definition)
90
87
  service_dockerfile = resolve_env_vars(service_dockerfile)
91
88
 
92
- service['image'] = f'demsking/{image_name}:{image_version}'
89
+ service['image'] = f'{image_prefix}{image_name}:{image_version}'
93
90
  service['build'] = {
94
91
  'context': '.',
95
92
  'dockerfile': service_dockerfile_file,
@@ -162,6 +159,7 @@ def resolve_compose_file(
162
159
  compose_data: dict,
163
160
  inject: bool = False,
164
161
  mode: list[ResolveMode] | None = None,
162
+ image_prefix: str,
165
163
  ) -> tuple[dict, list]:
166
164
  mode_value = mode or ['swarm']
167
165
  updated_compose_data = compose_data.copy()
@@ -185,7 +183,9 @@ def resolve_compose_file(
185
183
 
186
184
  service_deploy_labels.update(service_labels)
187
185
  parse_stack_values(service_deploy_labels)
188
- parse_local_volumes(driver.stack_id, service_name=service_name, service=service)
186
+ parse_local_volumes(
187
+ driver.stack_id, service_name=service_name, service=service, image_prefix=image_prefix
188
+ )
189
189
 
190
190
  parse_volumes(
191
191
  driver=driver,
@@ -242,7 +242,7 @@ def parse_service_configs(
242
242
  config_name = re.sub(
243
243
  r'_{2,}',
244
244
  '_',
245
- f"{service_name}_{source.replace('/', '_').replace('.', '_')}".replace('-', '_'),
245
+ f'{service_name}_{source.replace("/", "_").replace(".", "_")}'.replace('-', '_'),
246
246
  )
247
247
 
248
248
  if inject:
@@ -305,6 +305,7 @@ def parse_services(
305
305
  execute: Callable[[dict, list], None] | None = None,
306
306
  mode: list[ResolveMode] | None = None,
307
307
  inject: bool = False,
308
+ image_prefix: str,
308
309
  ) -> tuple[list, list]:
309
310
  services_files = glob.glob(os.path.join(stack, '*.yaml'))
310
311
  output_resolved_compose_data = []
@@ -332,6 +333,7 @@ def parse_services(
332
333
  compose_data=compose_data,
333
334
  inject=inject,
334
335
  mode=[x_mode],
336
+ image_prefix=image_prefix,
335
337
  )
336
338
 
337
339
  output_resolved_compose_data.append(resolved_compose_data)
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