From 5c96f75958ea948ded77d30b84f59e9e5d8c627e Mon Sep 17 00:00:00 2001 From: Pavel Sviderski Date: Thu, 14 Nov 2024 11:56:29 +1000 Subject: [PATCH] generate a name for the service --- go.mod | 8 +++---- go.sum | 6 ----- internal/cli/client/service.go | 41 +++++++++++++++++++++++++++++----- internal/corrosion/admin.go | 2 +- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 40c1ee41..2f16afb5 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/charmbracelet/huh v0.6.0 github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf github.com/dgraph-io/badger/v3 v3.2103.5 + github.com/distribution/reference v0.6.0 github.com/docker/docker v27.3.0+incompatible github.com/docker/go-connections v0.5.0 github.com/hashicorp/memberlist v0.5.1 @@ -22,8 +23,10 @@ require ( github.com/ipfs/go-ipld-format v0.6.0 github.com/ipfs/go-log/v2 v2.5.1 github.com/lmittmann/tint v1.0.5 + github.com/opencontainers/image-spec v1.1.0 github.com/siderolabs/discovery-api v0.1.4 github.com/siderolabs/discovery-client v0.1.9 + github.com/siderolabs/grpc-proxy v0.5.1 github.com/spf13/cobra v1.8.1 github.com/vishvananda/netlink v1.3.0 go.uber.org/zap v1.27.0 @@ -34,6 +37,7 @@ require ( golang.org/x/sys v0.26.0 golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 + google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.35.1 ) @@ -61,7 +65,6 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect - github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect @@ -142,7 +145,6 @@ require ( github.com/multiformats/go-multistream v0.5.0 // indirect github.com/multiformats/go-varint v0.0.7 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/polydawn/refmt v0.89.0 // indirect @@ -151,7 +153,6 @@ require ( github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/siderolabs/gen v0.4.8 // indirect - github.com/siderolabs/grpc-proxy v0.5.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/cast v1.7.0 // indirect @@ -170,7 +171,6 @@ require ( golang.org/x/tools v0.26.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect gotest.tools/v3 v3.5.1 // indirect gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 // indirect lukechampine.com/blake3 v1.3.0 // indirect diff --git a/go.sum b/go.sum index e8dbeeec..02f752de 100644 --- a/go.sum +++ b/go.sum @@ -815,8 +815,6 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed h1:3RgNmBoI9MZhsj3QxC+AP/qQhNwpCLOvYDYYsFrhFt0= google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed h1:J6izYgfBXAI3xTKLgxzTmUltdYaLsuBxFCgDHWJ/eXg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 h1:QCqS/PdaHTSWGvupk2F/ehwHtGc0/GYkT+3GAcR1CCc= google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -825,8 +823,6 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= -google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -838,8 +834,6 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/internal/cli/client/service.go b/internal/cli/client/service.go index 05b4863e..3611099b 100644 --- a/internal/cli/client/service.go +++ b/internal/cli/client/service.go @@ -4,11 +4,14 @@ import ( "context" "errors" "fmt" + "github.com/distribution/reference" "github.com/docker/docker/api/types/container" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/types/known/emptypb" "slices" + "strings" "uncloud/internal/machine/api/pb" + "uncloud/internal/secret" ) // ServiceOptions contains all the options for creating a service. @@ -28,6 +31,12 @@ type RunServiceResponse struct { func (c *Client) RunService(ctx context.Context, opts *ServiceOptions) (RunServiceResponse, error) { var resp RunServiceResponse + image, err := reference.ParseDockerRef(opts.Image) + if err != nil { + return resp, fmt.Errorf("invalid image: %w", err) + } + + // Find a machine to run the service on. listResp, err := c.ListMachines(ctx, &emptypb.Empty{}) if err != nil { return resp, fmt.Errorf("list machines: %w", err) @@ -53,16 +62,33 @@ func (c *Client) RunService(ctx context.Context, opts *ServiceOptions) (RunServi return resp, errors.New("no available machine to run the service") } + // Proxy Docker gRPC requests to the selected machine. machineIP, _ := machine.Machine.Network.ManagementIp.ToAddr() - resp.MachineName = machine.Machine.Name - md := metadata.Pairs("machines", machineIP.String()) ctx = metadata.NewOutgoingContext(ctx, md) - // TODO: generate a random service ID. - resp.ID = "todo-service-id" - // TODO: generate a random service name if not specified. - resp.Name = opts.Name + serviceID, err := secret.NewID() + if err != nil { + return resp, fmt.Errorf("generate service ID: %w", err) + } + + serviceName := opts.Name + // Generate a random service name if not specified. + if serviceName == "" { + // Get the image name without the repository and tag/digest parts. + imageName := reference.FamiliarName(image) + // Get the last part of the image name (path), e.g. "nginx" from "bitnami/nginx". + if i := strings.LastIndex(imageName, "/"); i != -1 { + imageName = imageName[i+1:] + } + // Append a random suffix to the image name to generate an optimistically unique service name. + suffix, err := secret.RandomAlphaNumeric(4) + if err != nil { + return resp, fmt.Errorf("generate random suffix: %w", err) + } + serviceName = fmt.Sprintf("%s-%s", imageName, suffix) + } + // TODO: generate a container name from the service name. // TODO: set service labels on the container. @@ -77,6 +103,9 @@ func (c *Client) RunService(ctx context.Context, opts *ServiceOptions) (RunServi return resp, fmt.Errorf("start container: %w", err) } + resp.ID = serviceID + resp.Name = serviceName + resp.MachineName = machine.Machine.Name return resp, nil } diff --git a/internal/corrosion/admin.go b/internal/corrosion/admin.go index 3340852c..660e2534 100644 --- a/internal/corrosion/admin.go +++ b/internal/corrosion/admin.go @@ -1,10 +1,10 @@ package corrosion import ( + "encoding/binary" "encoding/json" "errors" "fmt" - "gvisor.dev/gvisor/pkg/binary" "io" "net" "net/netip"