From 3ac166e6cb97cdd3e5b67d0afb27d117cf0aedf6 Mon Sep 17 00:00:00 2001 From: Pavel Sviderski Date: Thu, 5 Dec 2024 15:17:36 +1000 Subject: [PATCH] move common api types to api package --- internal/{service => api}/container.go | 3 +- internal/{service => api}/container_test.go | 2 +- internal/api/service.go | 49 +++++++++++++++++++-- internal/cli/client/service.go | 44 +++++++++--------- internal/machine/docker/manager.go | 8 ++-- internal/machine/store/container.go | 8 ++-- internal/service/service.go | 49 --------------------- 7 files changed, 80 insertions(+), 83 deletions(-) rename internal/{service => api}/container.go (97%) rename internal/{service => api}/container_test.go (99%) delete mode 100644 internal/service/service.go diff --git a/internal/service/container.go b/internal/api/container.go similarity index 97% rename from internal/service/container.go rename to internal/api/container.go index f90d771b..230f6583 100644 --- a/internal/service/container.go +++ b/internal/api/container.go @@ -1,4 +1,4 @@ -package service +package api import ( "github.com/docker/docker/api/types" @@ -12,7 +12,6 @@ const ( LabelServiceMode = "uncloud.service.mode" ) -// TODO: move to api package. type Container struct { types.Container } diff --git a/internal/service/container_test.go b/internal/api/container_test.go similarity index 99% rename from internal/service/container_test.go rename to internal/api/container_test.go index 304244b9..cbe47580 100644 --- a/internal/service/container_test.go +++ b/internal/api/container_test.go @@ -1,4 +1,4 @@ -package service +package api import ( "github.com/docker/docker/api/types" diff --git a/internal/api/service.go b/internal/api/service.go index 81b9f2d9..b1e49935 100644 --- a/internal/api/service.go +++ b/internal/api/service.go @@ -1,5 +1,11 @@ package api +import ( + "encoding/json" + "fmt" + "uncloud/internal/machine/api/pb" +) + const ( ServiceModeReplicated = "replicated" ServiceModeGlobal = "global" @@ -19,7 +25,44 @@ type ContainerSpec struct { Init *bool } -type MachineContainerID struct { - MachineID string - ContainerID string +type Service struct { + ID string + Name string + Mode string + Containers []MachineContainer +} + +type MachineContainer struct { + MachineID string + Container Container +} + +func ServiceFromProto(s *pb.Service) (Service, error) { + var err error + containers := make([]MachineContainer, len(s.Containers)) + for i, sc := range s.Containers { + containers[i], err = machineContainerFromProto(sc) + if err != nil { + return Service{}, err + } + } + + return Service{ + ID: s.Id, + Name: s.Name, + Mode: s.Mode, + Containers: containers, + }, nil +} + +func machineContainerFromProto(sc *pb.Service_Container) (MachineContainer, error) { + var c Container + if err := json.Unmarshal(sc.Container, &c); err != nil { + return MachineContainer{}, fmt.Errorf("unmarshal container: %w", err) + } + + return MachineContainer{ + MachineID: sc.MachineId, + Container: c, + }, nil } diff --git a/internal/cli/client/service.go b/internal/cli/client/service.go index 3795ba94..af091bb2 100644 --- a/internal/cli/client/service.go +++ b/internal/cli/client/service.go @@ -19,7 +19,6 @@ import ( "uncloud/internal/machine/api/pb" machinedocker "uncloud/internal/machine/docker" "uncloud/internal/secret" - "uncloud/internal/service" ) // ServiceOptions contains all the options for creating a service. @@ -36,7 +35,12 @@ type ServiceOptions struct { type RunServiceResponse struct { ID string Name string - Containers []api.MachineContainerID + Containers []MachineContainerID +} + +type MachineContainerID struct { + MachineID string + ContainerID string } func (cli *Client) RunService(ctx context.Context, spec api.ServiceSpec) (RunServiceResponse, error) { @@ -124,7 +128,7 @@ func (cli *Client) runReplicatedService(ctx context.Context, id string, spec api return resp, fmt.Errorf("run container: %w", err) } - resp.Containers = append(resp.Containers, api.MachineContainerID{ + resp.Containers = append(resp.Containers, MachineContainerID{ MachineID: m.Machine.Id, ContainerID: runResp.ID, }) @@ -152,13 +156,13 @@ func (cli *Client) runContainer( Cmd: spec.Container.Command, Image: spec.Container.Image, Labels: map[string]string{ - service.LabelServiceID: serviceID, - service.LabelServiceName: spec.Name, - service.LabelManaged: "", + api.LabelServiceID: serviceID, + api.LabelServiceName: spec.Name, + api.LabelManaged: "", }, } if spec.Mode == api.ServiceModeGlobal { - config.Labels[service.LabelServiceMode] = api.ServiceModeGlobal + config.Labels[api.LabelServiceMode] = api.ServiceModeGlobal } hostConfig := &container.HostConfig{ @@ -223,7 +227,7 @@ func (cli *Client) runGlobalService(ctx context.Context, id string, spec api.Ser return resp, fmt.Errorf("run container: %w", err) } - resp.Containers = append(resp.Containers, api.MachineContainerID{ + resp.Containers = append(resp.Containers, MachineContainerID{ MachineID: m.Machine.Id, ContainerID: runResp.ID, }) @@ -252,8 +256,8 @@ func firstAvailableMachine(machines []*pb.MachineMember) *pb.MachineMember { // InspectService returns detailed information about a service and its containers. // The id parameter can be either a service ID or name. -func (cli *Client) InspectService(ctx context.Context, id string) (service.Service, error) { - var svc service.Service +func (cli *Client) InspectService(ctx context.Context, id string) (api.Service, error) { + var svc api.Service machines, err := cli.ListMachines(ctx) if err != nil { @@ -278,8 +282,8 @@ func (cli *Client) InspectService(ctx context.Context, id string) (service.Servi opts := container.ListOptions{ All: true, Filters: filters.NewArgs( - filters.Arg("label", service.LabelServiceID), - filters.Arg("label", service.LabelManaged), + filters.Arg("label", api.LabelServiceID), + filters.Arg("label", api.LabelManaged), ), } machineContainers, err := cli.ListContainers(listCtx, opts) @@ -289,7 +293,7 @@ func (cli *Client) InspectService(ctx context.Context, id string) (service.Servi // Collect all containers on all machines that belong to the specified service. foundByID := false - var containers []service.MachineContainer + var containers []api.MachineContainer for _, mc := range machineContainers { // Metadata can be nil if the request was broadcasted to only one machine. if mc.Metadata == nil && len(machineContainers) > 1 { @@ -318,9 +322,9 @@ func (cli *Client) InspectService(ctx context.Context, id string) (service.Servi } for _, c := range mc.Containers { - ctr := service.Container{Container: c} + ctr := api.Container{Container: c} if ctr.ServiceID() == id || ctr.ServiceName() == id { - containers = append(containers, service.MachineContainer{ + containers = append(containers, api.MachineContainer{ MachineID: machineID, Container: ctr, }) @@ -340,7 +344,7 @@ func (cli *Client) InspectService(ctx context.Context, id string) (service.Servi // may not prevent this), or a service name might match another service's ID. In these cases, matching by ID takes // priority over matching by name. if foundByID { - containers = slices.DeleteFunc(containers, func(mc service.MachineContainer) bool { + containers = slices.DeleteFunc(containers, func(mc api.MachineContainer) bool { return mc.Container.ServiceID() != id }) } else { @@ -353,7 +357,7 @@ func (cli *Client) InspectService(ctx context.Context, id string) (service.Servi } } - svc = service.Service{ + svc = api.Service{ ID: containers[0].Container.ServiceID(), Name: containers[0].Container.ServiceName(), Mode: containers[0].Container.ServiceMode(), @@ -369,8 +373,8 @@ func (cli *Client) InspectService(ctx context.Context, id string) (service.Servi // InspectServiceFromStore returns detailed information about a service and its containers from the distributed store. // Due to eventual consistency of the store, the returned information may not reflect the most recent changes. // The id parameter can be either a service ID or name. -func (cli *Client) InspectServiceFromStore(ctx context.Context, id string) (service.Service, error) { - var svc service.Service +func (cli *Client) InspectServiceFromStore(ctx context.Context, id string) (api.Service, error) { + var svc api.Service resp, err := cli.MachineClient.InspectService(ctx, &pb.InspectServiceRequest{Id: id}) if err != nil { @@ -382,7 +386,7 @@ func (cli *Client) InspectServiceFromStore(ctx context.Context, id string) (serv return svc, err } - svc, err = service.FromProto(resp.Service) + svc, err = api.ServiceFromProto(resp.Service) if err != nil { return svc, fmt.Errorf("from proto: %w", err) } diff --git a/internal/machine/docker/manager.go b/internal/machine/docker/manager.go index 3dd26b81..8f725b7b 100644 --- a/internal/machine/docker/manager.go +++ b/internal/machine/docker/manager.go @@ -10,8 +10,8 @@ import ( "github.com/docker/docker/client" "log/slog" "time" + "uncloud/internal/api" "uncloud/internal/machine/store" - "uncloud/internal/service" ) const ( @@ -152,8 +152,8 @@ func (m *Manager) syncContainersToStore(ctx context.Context) error { // List only Uncloud service containers identified by their labels. containers, err := m.client.ContainerList(ctx, dockercontainer.ListOptions{ Filters: filters.NewArgs( - filters.Arg("label", service.LabelServiceID), - filters.Arg("label", service.LabelServiceName), + filters.Arg("label", api.LabelServiceID), + filters.Arg("label", api.LabelServiceName), ), }) if err != nil { @@ -185,7 +185,7 @@ func (m *Manager) syncContainersToStore(ctx context.Context) error { // Create or update the current Docker containers in the store. for _, dc := range containers { - c := &service.Container{Container: dc} + c := &api.Container{Container: dc} if err = m.store.CreateOrUpdateContainer(ctx, c, m.machineID); err != nil { storeErr = errors.Join(storeErr, fmt.Errorf("create or update container %q: %w", c.ID, err)) } diff --git a/internal/machine/store/container.go b/internal/machine/store/container.go index f7f772b0..40200c30 100644 --- a/internal/machine/store/container.go +++ b/internal/machine/store/container.go @@ -8,7 +8,7 @@ import ( "log/slog" "strings" "time" - "uncloud/internal/service" + "uncloud/internal/api" ) const ( @@ -22,7 +22,7 @@ const ( ) type ContainerRecord struct { - Container *service.Container + Container *api.Container MachineID string SyncStatus string UpdatedAt time.Time @@ -47,7 +47,7 @@ type DeleteOptions struct { // CreateOrUpdateContainer creates a new container record or updates an existing one in the store database. // The container is associated with the given machine ID that indicates which machine the container is running on. -func (s *Store) CreateOrUpdateContainer(ctx context.Context, c *service.Container, machineID string) error { +func (s *Store) CreateOrUpdateContainer(ctx context.Context, c *api.Container, machineID string) error { cJSON, err := json.Marshal(c) if err != nil { return fmt.Errorf("marshal container: %w", err) @@ -113,7 +113,7 @@ func (s *Store) ListContainers(ctx context.Context, opts ListOptions) ([]*Contai return nil, fmt.Errorf("scan container record: %w", err) } - var c service.Container + var c api.Container if err = json.Unmarshal([]byte(cJSON), &c); err != nil { return nil, fmt.Errorf("unmarshal container: %w", err) } diff --git a/internal/service/service.go b/internal/service/service.go deleted file mode 100644 index d2d69192..00000000 --- a/internal/service/service.go +++ /dev/null @@ -1,49 +0,0 @@ -package service - -import ( - "encoding/json" - "fmt" - "uncloud/internal/machine/api/pb" -) - -type Service struct { - ID string - Name string - Mode string - Containers []MachineContainer -} - -type MachineContainer struct { - MachineID string - Container Container -} - -func FromProto(s *pb.Service) (Service, error) { - var err error - containers := make([]MachineContainer, len(s.Containers)) - for i, sc := range s.Containers { - containers[i], err = machineContainerFromProto(sc) - if err != nil { - return Service{}, err - } - } - - return Service{ - ID: s.Id, - Name: s.Name, - Mode: s.Mode, - Containers: containers, - }, nil -} - -func machineContainerFromProto(sc *pb.Service_Container) (MachineContainer, error) { - var c Container - if err := json.Unmarshal(sc.Container, &c); err != nil { - return MachineContainer{}, fmt.Errorf("unmarshal container: %w", err) - } - - return MachineContainer{ - MachineID: sc.MachineId, - Container: c, - }, nil -}