mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 19:13:34 +00:00
feat: print service endpoints on service creation
This commit is contained in:
@@ -109,9 +109,21 @@ func run(ctx context.Context, uncli *cli.CLI, opts runOptions) error {
|
|||||||
}
|
}
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
if _, err = client.RunService(ctx, spec); err != nil {
|
resp, err := client.RunService(ctx, spec)
|
||||||
|
if err != nil {
|
||||||
return fmt.Errorf("run service: %w", err)
|
return fmt.Errorf("run service: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
svc, err := client.InspectService(ctx, resp.ID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("inspect service: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Printf("%s endpoints:\n", svc.Name)
|
||||||
|
for _, endpoint := range svc.Endpoints() {
|
||||||
|
fmt.Printf(" • %s\n", endpoint)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
|
"maps"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"slices"
|
||||||
"uncloud/internal/machine/api/pb"
|
"uncloud/internal/machine/api/pb"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -79,6 +81,50 @@ type MachineContainer struct {
|
|||||||
Container Container
|
Container Container
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Endpoints returns the exposed HTTP and HTTPS endpoints of the service.
|
||||||
|
func (s *Service) Endpoints() []string {
|
||||||
|
endpoints := make(map[string]struct{})
|
||||||
|
|
||||||
|
// Container specs may differ between containers in the same service, e.g. during a rolling update,
|
||||||
|
// so we need to collect all unique endpoints.
|
||||||
|
for _, ctr := range s.Containers {
|
||||||
|
ports, err := ctr.Container.ServicePorts()
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, port := range ports {
|
||||||
|
protocol := ""
|
||||||
|
switch port.Protocol {
|
||||||
|
case ProtocolHTTP:
|
||||||
|
protocol = "http"
|
||||||
|
case ProtocolHTTPS:
|
||||||
|
protocol = "https"
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if port.Hostname == "" {
|
||||||
|
// There shouldn't be http(s) ports without a hostname but just in case ignore them.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint := fmt.Sprintf("%s://%s", protocol, port.Hostname)
|
||||||
|
if port.PublishedPort != 0 {
|
||||||
|
// For non-standard ports (80/443), include the port in the URL.
|
||||||
|
if !(port.Protocol == ProtocolHTTP && port.PublishedPort == 80) &&
|
||||||
|
!(port.Protocol == ProtocolHTTPS && port.PublishedPort == 443) {
|
||||||
|
endpoint += fmt.Sprintf(":%d", port.PublishedPort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints[endpoint] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return slices.Sorted(maps.Keys(endpoints))
|
||||||
|
}
|
||||||
|
|
||||||
func ServiceFromProto(s *pb.Service) (Service, error) {
|
func ServiceFromProto(s *pb.Service) (Service, error) {
|
||||||
var err error
|
var err error
|
||||||
containers := make([]MachineContainer, len(s.Containers))
|
containers := make([]MachineContainer, len(s.Containers))
|
||||||
|
|||||||
Reference in New Issue
Block a user