feat(actions): resolve containers by label and forward full requests
- New ResolveContainer inspects a container by id, name, service label or image name (case-insensitive), falling back to label matching when Docker cannot resolve the reference. - The action proxy uses the org.dcntrlized.port label, falling back to the first mapped guest port, and no longer hardcodes the host port. - Action forwarding preserves the request method, body, query string and hop-by-hop-safe headers, and passes non-2xx status and body through.
This commit is contained in:
@@ -209,6 +209,46 @@ func ExtractNetworkInfo(ctx context.Context, dc *DockerClient, inspectData conta
|
||||
return netInfo, true, nil
|
||||
}
|
||||
|
||||
// ResolveContainer inspects the given container reference. It accepts a full or partial
|
||||
// container ID, a container name, or a service/image name (matched case-insensitively).
|
||||
func ResolveContainer(ctx context.Context, dc *DockerClient, ref string) (container.InspectResponse, error) {
|
||||
inspectData, err := dc.Client.ContainerInspect(ctx, ref)
|
||||
if err == nil {
|
||||
return inspectData, nil
|
||||
}
|
||||
|
||||
// Docker only resolves IDs and container names, so fall back to matching the
|
||||
// org.dcntrlized.service label or the image name when the reference isn't one.
|
||||
containers, listErr := dc.Client.ContainerList(ctx, container.ListOptions{
|
||||
All: true,
|
||||
Filters: filters.NewArgs(filters.Arg("label", "org.dcntrlized.service")),
|
||||
})
|
||||
if listErr != nil {
|
||||
return container.InspectResponse{}, err
|
||||
}
|
||||
|
||||
refLower := strings.ToLower(ref)
|
||||
var matches []container.Summary
|
||||
for _, c := range containers {
|
||||
if len(c.Names) == 0 {
|
||||
continue
|
||||
}
|
||||
service := strings.ToLower(c.Labels["org.dcntrlized.service"])
|
||||
image := strings.ToLower(strings.SplitN(c.Image, ":", 2)[0])
|
||||
name := strings.ToLower(strings.TrimPrefix(c.Names[0], "/"))
|
||||
if service == refLower || image == refLower || name == refLower {
|
||||
matches = append(matches, c)
|
||||
}
|
||||
}
|
||||
if len(matches) == 1 {
|
||||
return dc.Client.ContainerInspect(ctx, matches[0].ID)
|
||||
}
|
||||
if len(matches) > 1 {
|
||||
return container.InspectResponse{}, fmt.Errorf("multiple containers match %q", ref)
|
||||
}
|
||||
return container.InspectResponse{}, fmt.Errorf("container %q not found", ref)
|
||||
}
|
||||
|
||||
// GetContainerMetadata collects the primary useful metadata for a given container.
|
||||
func GetContainerMetadata(ctx context.Context, dc *DockerClient, containerID string) (*ContainerMetadata, error) {
|
||||
inspectData, err := dc.Client.ContainerInspect(ctx, containerID)
|
||||
|
||||
Reference in New Issue
Block a user