@tdk-landscape/tdk-cli-core 1.3.120 → 1.3.122
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.
- package/CHANGELOG.md +1 -0
- package/README.md +21 -14
- package/cli/dist/cli.js +1 -1
- package/cli/dist/commands/config.js +6 -2
- package/cli/dist/commands/doctor.js +64 -7
- package/cli/dist/commands/help.js +17 -1
- package/cli/dist/commands/logs.js +34 -7
- package/cli/dist/commands/networks.js +1 -1
- package/cli/dist/commands/resources.js +1 -1
- package/cli/dist/commands/stack.js +94 -22
- package/cli/dist/commands/status.js +35 -2
- package/cli/dist/commands/ui.js +105 -9
- package/cli/dist/commands/up.js +105 -28
- package/cli/dist/components/ServiceIssues.js +12 -0
- package/cli/dist/components/TabBar.js +3 -2
- package/cli/dist/components/index.js +1 -0
- package/cli/dist/generator/__tests__/golden-helpers.js +42 -0
- package/cli/dist/generator/template-engine.js +5 -3
- package/cli/dist/utils/atomic-write.js +35 -0
- package/cli/dist/utils/bun-floor.js +8 -0
- package/cli/dist/utils/cold-preflight.js +6 -4
- package/cli/dist/utils/doctor-runtime.js +6 -6
- package/cli/dist/utils/doctor-wiring.js +62 -1
- package/cli/dist/utils/errors.js +20 -2
- package/cli/dist/utils/host-port-plan.js +3 -0
- package/cli/dist/utils/machine-output.js +8 -1
- package/cli/dist/utils/port-conflict-fix.js +24 -0
- package/cli/dist/utils/port-fallback-notice.js +18 -0
- package/cli/dist/utils/port-listener-probe.js +19 -0
- package/cli/dist/utils/secret-redaction.js +55 -0
- package/cli/dist/utils/service-config-checks.js +188 -0
- package/cli/dist/utils/service-runtime-state.js +67 -0
- package/cli/dist/utils/services.js +2 -15
- package/cli/dist/utils/single-flight.js +20 -0
- package/cli/dist/utils/stack-status.js +15 -0
- package/cli/dist/utils/startup-report.js +73 -0
- package/cli/dist/utils/suggestions.js +58 -0
- package/cli/dist/utils/tilt-events.js +195 -0
- package/cli/dist/utils/tilt-resource-state.js +12 -0
- package/cli/dist/utils/tilt-startup.js +7 -0
- package/cli/dist/utils/tilt-unreachable-message.js +8 -0
- package/cli/dist/utils/ui-service-state.js +35 -0
- package/cli/dist/utils/up-readiness.js +2 -0
- package/cli/package.json +1 -1
- package/cli/templates/.tiltignore.hbs +1 -2
- package/cli/templates/TILT_RESOURCE_DEFAULTS.star.hbs +1 -1
- package/cli/templates/TILT_TECH_STACK.star.hbs +5 -5
- package/cli/templates/Tiltfile.hbs +3 -3
- package/cli/templates/spec.master.hbs +1 -1
- package/engine/topologies/platform/docker/compose/compose.star +1 -86
- package/engine/topologies/platform/docker/compose/traefik_standalone.star +4 -4
- package/engine/topologies/platform/docker/networking/traefik.star +40 -7
- package/engine/topologies/platform/docker/networking/traefik_helpers.star +1 -1
- package/engine/topologies/tilt/resources/infra-loader.star +3 -2
- package/engine/topologies/tilt/resources/orchestrator/apply_compose_resource_registration.star +20 -0
- package/package.json +1 -1
|
@@ -83,6 +83,22 @@ def get_frontend_traefik_labels(res_name, domain, base_path, port, traefik_host=
|
|
|
83
83
|
|
|
84
84
|
return labels
|
|
85
85
|
|
|
86
|
+
def _stack_is_shared(manifest):
|
|
87
|
+
"""True when this backend shares its stack with another routable backend (`_stackBackendCount`, set by register_compose_resources).
|
|
88
|
+
|
|
89
|
+
The stack-scoped routers (the host/`pathPrefix` router and `<name>-management`) carry one rule per stack. With two backends in
|
|
90
|
+
one stack they would carry the same rule, so Traefik would pick between them arbitrarily. Each backend keeps its own
|
|
91
|
+
`<name>-project` router (`/api/<name>`).
|
|
92
|
+
"""
|
|
93
|
+
return bool(manifest) and manifest.get('_stackBackendCount', 1) > 1
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _explicit_backend_route(manifest):
|
|
97
|
+
"""The `traefik.host` / `traefik.pathPrefix` a manifest set on purpose, as (host, path); either may be empty."""
|
|
98
|
+
traefik_cfg = (manifest.get('traefik') or {}) if manifest else {}
|
|
99
|
+
return traefik_cfg.get('host') or '', traefik_cfg.get('pathPrefix') or ''
|
|
100
|
+
|
|
101
|
+
|
|
86
102
|
def get_backend_traefik_labels(
|
|
87
103
|
resource_entry_name,
|
|
88
104
|
traefik_host,
|
|
@@ -123,12 +139,31 @@ def get_backend_traefik_labels(
|
|
|
123
139
|
# No middleware if path is empty - router has no middlewares
|
|
124
140
|
middleware_config = ""
|
|
125
141
|
|
|
126
|
-
|
|
127
|
-
|
|
142
|
+
stack_shared = _stack_is_shared(manifest)
|
|
143
|
+
explicit_host, explicit_path = _explicit_backend_route(manifest)
|
|
144
|
+
if stack_shared:
|
|
145
|
+
# Another backend in this stack would match the same stack rule, so it is not emitted. The service labels stay (the
|
|
146
|
+
# -project router points at the service). A manifest that set its own host or pathPrefix keeps a router, but one whose
|
|
147
|
+
# rule is only what it set, never the shared stack host or path.
|
|
148
|
+
backend_route_rule = backend_rule(explicit_host, explicit_path)
|
|
149
|
+
|
|
150
|
+
if stack_shared and not backend_route_rule:
|
|
151
|
+
backend_router_labels = ""
|
|
152
|
+
else:
|
|
153
|
+
backend_router_labels = """ - "traefik.http.routers.{resource_entry_name}.rule={backend_route_rule}"
|
|
128
154
|
- "traefik.http.routers.{resource_entry_name}.entrypoints={backend_entrypoints}"
|
|
129
155
|
- "traefik.http.routers.{resource_entry_name}.service={traefik_resource_name}"
|
|
130
156
|
{middleware_config}
|
|
131
|
-
|
|
157
|
+
""".format(
|
|
158
|
+
resource_entry_name=resource_entry_name,
|
|
159
|
+
backend_route_rule=backend_route_rule,
|
|
160
|
+
backend_entrypoints=backend_entrypoints,
|
|
161
|
+
traefik_resource_name=traefik_resource_name,
|
|
162
|
+
middleware_config=middleware_config,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
labels = """ - "{traefik_enable_label}"
|
|
166
|
+
{backend_router_labels} - "traefik.http.services.{traefik_resource_name}.loadbalancer.server.port={internal_port}"
|
|
132
167
|
- "traefik.http.services.{traefik_resource_name}.loadbalancer.healthcheck.path={health_path}"
|
|
133
168
|
- "traefik.http.services.{traefik_resource_name}.loadbalancer.healthcheck.interval={health_interval}"
|
|
134
169
|
- "traefik.http.services.{traefik_resource_name}.loadbalancer.healthcheck.timeout={health_timeout}"
|
|
@@ -137,10 +172,8 @@ def get_backend_traefik_labels(
|
|
|
137
172
|
""".format(
|
|
138
173
|
resource_entry_name=resource_entry_name,
|
|
139
174
|
traefik_enable_label=TRAEFIK_ENABLE_LABEL,
|
|
140
|
-
|
|
141
|
-
backend_entrypoints=backend_entrypoints,
|
|
175
|
+
backend_router_labels=backend_router_labels,
|
|
142
176
|
traefik_resource_name=traefik_resource_name,
|
|
143
|
-
middleware_config=middleware_config,
|
|
144
177
|
internal_port=internal_port,
|
|
145
178
|
health_path=health_path,
|
|
146
179
|
health_interval=TRAEFIK_HEALTHCHECK_INTERVAL,
|
|
@@ -188,7 +221,7 @@ def get_backend_traefik_labels(
|
|
|
188
221
|
router_priority=router_priority,
|
|
189
222
|
)
|
|
190
223
|
|
|
191
|
-
if management_path and management_path != api_path:
|
|
224
|
+
if management_path and management_path != api_path and not stack_shared:
|
|
192
225
|
labels += """
|
|
193
226
|
- "traefik.http.routers.{resource_entry_name}-management.rule=Host(`{api_host}`) && PathPrefix(`{management_path}`)"
|
|
194
227
|
- "traefik.http.routers.{resource_entry_name}-management.entrypoints={project_entrypoints}"
|
|
@@ -64,7 +64,7 @@ def frontend_rule(res_name, base_path, traefik_host):
|
|
|
64
64
|
|
|
65
65
|
def backend_rule(traefik_host, traefik_path):
|
|
66
66
|
parts = []
|
|
67
|
-
if TRAEFIK_ENABLE_BACKEND_HOST_RULE:
|
|
67
|
+
if TRAEFIK_ENABLE_BACKEND_HOST_RULE and traefik_host:
|
|
68
68
|
parts.append("Host(`{host}`)".format(host=traefik_host))
|
|
69
69
|
if TRAEFIK_ENABLE_BACKEND_PATH_RULE and traefik_path:
|
|
70
70
|
parts.append("PathPrefix(`{path}`)".format(path=traefik_path))
|
|
@@ -70,7 +70,7 @@ services:
|
|
|
70
70
|
POSTGRES_PASSWORD: ${{DB_PASSWORD}}
|
|
71
71
|
POSTGRES_DB: postgres
|
|
72
72
|
ports:
|
|
73
|
-
- "{host_port}:5432"
|
|
73
|
+
- "{bind_address}:{host_port}:5432"
|
|
74
74
|
volumes:
|
|
75
75
|
- {name}_postgres_data:/var/lib/postgresql/data
|
|
76
76
|
networks:
|
|
@@ -88,7 +88,7 @@ networks:
|
|
|
88
88
|
|
|
89
89
|
volumes:
|
|
90
90
|
{name}_postgres_data:
|
|
91
|
-
""".format(name=name, database_network=database_network, host_port=os.environ.get('TDK_POSTGRES_PORT', '15432'))
|
|
91
|
+
""".format(name=name, database_network=database_network, host_port=os.environ.get('TDK_POSTGRES_PORT', '15432'), bind_address=os.environ.get('TDK_BIND_ADDRESS', '127.0.0.1'))
|
|
92
92
|
|
|
93
93
|
|
|
94
94
|
def _ensure_database_management_compose(root_prefix, write_fn):
|
|
@@ -236,6 +236,7 @@ def _load_standalone_traefik(root_prefix, env_file, write_fn):
|
|
|
236
236
|
sablier_enabled,
|
|
237
237
|
os.environ.get('TDK_HTTP_PORT', '8080'),
|
|
238
238
|
os.environ.get('TDK_HTTPS_PORT', '8443'),
|
|
239
|
+
os.environ.get('TDK_BIND_ADDRESS', '127.0.0.1'),
|
|
239
240
|
)
|
|
240
241
|
if write_fn:
|
|
241
242
|
write_fn(compose_rel, content)
|
package/engine/topologies/tilt/resources/orchestrator/apply_compose_resource_registration.star
CHANGED
|
@@ -632,6 +632,21 @@ def _build_resource_config(res, manifest, resource_config, full_res_path, infra_
|
|
|
632
632
|
}
|
|
633
633
|
|
|
634
634
|
|
|
635
|
+
def count_routable_backends_by_stack(resource_config, resource_manifests, default_stack):
|
|
636
|
+
"""Count the backends of each stack that get a Traefik route (workers, frontends, SDKs, libraries and unproxied BYO do not)."""
|
|
637
|
+
counts = {}
|
|
638
|
+
for resource in resource_config.get('resources', []):
|
|
639
|
+
manifest = resource_manifests.get(resource['name'], {})
|
|
640
|
+
app_type = manifest.get('appType', 'backend')
|
|
641
|
+
if resource.get('frontend', False) or app_type in ['frontend', 'worker', 'library', 'sdk', 'infra']:
|
|
642
|
+
continue
|
|
643
|
+
if app_type == 'bring-your-own' and not manifest.get('exposeViaProxy', True):
|
|
644
|
+
continue
|
|
645
|
+
stack = manifest.get('stack', default_stack)
|
|
646
|
+
counts[stack] = counts.get(stack, 0) + 1
|
|
647
|
+
return counts
|
|
648
|
+
|
|
649
|
+
|
|
635
650
|
def register_compose_resources(resource_config, ctx, runtime_flags, manifest_state):
|
|
636
651
|
"""Register all compose resources for a service."""
|
|
637
652
|
resource_name = resource_config.get('name', '')
|
|
@@ -695,6 +710,7 @@ def register_compose_resources(resource_config, ctx, runtime_flags, manifest_sta
|
|
|
695
710
|
|
|
696
711
|
resource_entries = []
|
|
697
712
|
resource_configs = []
|
|
713
|
+
stack_backend_counts = count_routable_backends_by_stack(resource_config, resource_manifests, resource_name)
|
|
698
714
|
|
|
699
715
|
for res in resource_config.get('resources', []):
|
|
700
716
|
if _should_skip_frontend(res, should_enable):
|
|
@@ -702,6 +718,10 @@ def register_compose_resources(resource_config, ctx, runtime_flags, manifest_sta
|
|
|
702
718
|
|
|
703
719
|
full_res_path = res.get('_resource_path', resource_path + '/' + res['name'])
|
|
704
720
|
manifest = resource_manifests.get(res['name'], {})
|
|
721
|
+
if manifest:
|
|
722
|
+
# Tell the Traefik label generator how many routable backends share this stack (see _stack_is_shared in networking/traefik.star).
|
|
723
|
+
manifest = dict(manifest)
|
|
724
|
+
manifest['_stackBackendCount'] = stack_backend_counts.get(manifest.get('stack', resource_name), 1)
|
|
705
725
|
|
|
706
726
|
# Skip non-app resources - they don't use the golden app Dockerfile pipeline.
|
|
707
727
|
# infra (e.g. verdaccio) is loaded via registries/verdaccio_loader.star instead.
|