diff --git a/aci/volumes.go b/aci/volumes.go index e3408ca34..151ee5bfe 100644 --- a/aci/volumes.go +++ b/aci/volumes.go @@ -63,7 +63,7 @@ func (cs *aciVolumeService) List(ctx context.Context) ([]volumes.Volume, error) for fileSharePage.NotDone() { values := fileSharePage.Values() for _, fileShare := range values { - fileShares = append(fileShares, toVolume(account, *fileShare.Name)) + fileShares = append(fileShares, toVolume(*account.Name, *fileShare.Name)) } if err := fileSharePage.NextWithContext(ctx); err != nil { return nil, err @@ -146,7 +146,7 @@ func (cs *aciVolumeService) Create(ctx context.Context, name string, options int return volumes.Volume{}, err } w.Event(event(name, progress.Done, "Created")) - return toVolume(account, *fileShare.Name), nil + return toVolume(*account.Name, *fileShare.Name), nil } func event(resource string, status progress.EventStatus, text string) progress.Event { @@ -197,12 +197,10 @@ func (cs *aciVolumeService) Delete(ctx context.Context, id string, options inter if err != nil { return err } - tokens := strings.Split(id, "/") - if len(tokens) != 2 { - return errors.New("invalid format for volume ID, expected storageaccount/fileshare") + storageAccount, fileshare, err := getStorageAccountAndFileshare(id) + if err != nil { + return err } - storageAccount := tokens[0] - fileshare := tokens[1] fileShareClient, err := login.NewFileShareClient(cs.aciContext.SubscriptionID) if err != nil { @@ -240,10 +238,26 @@ func (cs *aciVolumeService) Delete(ctx context.Context, id string, options inter return err } -func toVolume(account storage.Account, fileShareName string) volumes.Volume { +func (cs *aciVolumeService) Inspect(ctx context.Context, id string) (volumes.Volume, error) { + storageAccount, fileshareName, err := getStorageAccountAndFileshare(id) + if err != nil { + return volumes.Volume{}, err + } + fileShareClient, err := login.NewFileShareClient(cs.aciContext.SubscriptionID) + if err != nil { + return volumes.Volume{}, err + } + _, err = fileShareClient.Get(ctx, cs.aciContext.ResourceGroup, storageAccount, fileshareName, "") + if err != nil { // Just checks if it exists + return volumes.Volume{}, err + } + return toVolume(storageAccount, fileshareName), nil +} + +func toVolume(storageAccountName string, fileShareName string) volumes.Volume { return volumes.Volume{ - ID: volumeID(*account.Name, fileShareName), - Description: fmt.Sprintf("Fileshare %s in %s storage account", fileShareName, *account.Name), + ID: volumeID(storageAccountName, fileShareName), + Description: fmt.Sprintf("Fileshare %s in %s storage account", fileShareName, storageAccountName), } } @@ -261,3 +275,11 @@ func defaultStorageAccountParams(aciContext store.AciContext) storage.AccountCre Tags: tags, } } + +func getStorageAccountAndFileshare(volumeID string) (string, string, error) { + tokens := strings.Split(volumeID, "/") + if len(tokens) != 2 { + return "", "", errors.New("invalid format for volume ID, expected storageaccount/fileshare") + } + return tokens[0], tokens[1], nil +} diff --git a/api/client/volume.go b/api/client/volume.go index b08baaae5..23d99c3d7 100644 --- a/api/client/volume.go +++ b/api/client/volume.go @@ -37,3 +37,7 @@ func (c *volumeService) Create(ctx context.Context, name string, options interfa func (c *volumeService) Delete(ctx context.Context, id string, options interface{}) error { return errdefs.ErrNotImplemented } + +func (c *volumeService) Inspect(ctx context.Context, volumeID string) (volumes.Volume, error) { + return volumes.Volume{}, errdefs.ErrNotImplemented +} diff --git a/api/volumes/api.go b/api/volumes/api.go index e32222c70..22f21dfa7 100644 --- a/api/volumes/api.go +++ b/api/volumes/api.go @@ -34,4 +34,6 @@ type Service interface { Create(ctx context.Context, name string, options interface{}) (Volume, error) // Delete deletes an existing volume Delete(ctx context.Context, volumeID string, options interface{}) error + // Inspect inspects an existing volume + Inspect(ctx context.Context, volumeID string) (Volume, error) } diff --git a/cli/cmd/volume/acivolume.go b/cli/cmd/volume/acivolume.go index 7e5a878d2..d1d6e5d8f 100644 --- a/cli/cmd/volume/acivolume.go +++ b/cli/cmd/volume/acivolume.go @@ -26,6 +26,7 @@ import ( "github.com/docker/compose-cli/aci" "github.com/docker/compose-cli/api/client" "github.com/docker/compose-cli/cli/formatter" + formatter2 "github.com/docker/compose-cli/formatter" "github.com/docker/compose-cli/progress" ) @@ -40,6 +41,7 @@ func ACICommand() *cobra.Command { createVolume(), listVolume(), rmVolume(), + inspectVolume(), ) return cmd } @@ -101,3 +103,28 @@ func rmVolume() *cobra.Command { } return cmd } + +func inspectVolume() *cobra.Command { + cmd := &cobra.Command{ + Use: "inspect VOLUME [VOLUME...]", + Short: "Inspect one or more volumes.", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := client.New(cmd.Context()) + if err != nil { + return err + } + v, err := c.VolumeService().Inspect(cmd.Context(), args[0]) + if err != nil { + return err + } + outJSON, err := formatter2.ToStandardJSON(v) + if err != nil { + return err + } + fmt.Print(outJSON) + return nil + }, + } + return cmd +} diff --git a/protos/volumes/v1/volumes.pb.go b/protos/volumes/v1/volumes.pb.go index 0a5991361..b6b2433c7 100644 --- a/protos/volumes/v1/volumes.pb.go +++ b/protos/volumes/v1/volumes.pb.go @@ -438,6 +438,100 @@ func (*VolumesDeleteResponse) Descriptor() ([]byte, []int) { return file_protos_volumes_v1_volumes_proto_rawDescGZIP(), []int{7} } +type VolumesInspectRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *VolumesInspectRequest) Reset() { + *x = VolumesInspectRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_protos_volumes_v1_volumes_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *VolumesInspectRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VolumesInspectRequest) ProtoMessage() {} + +func (x *VolumesInspectRequest) ProtoReflect() protoreflect.Message { + mi := &file_protos_volumes_v1_volumes_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VolumesInspectRequest.ProtoReflect.Descriptor instead. +func (*VolumesInspectRequest) Descriptor() ([]byte, []int) { + return file_protos_volumes_v1_volumes_proto_rawDescGZIP(), []int{8} +} + +func (x *VolumesInspectRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type VolumesInspectResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Volume *Volume `protobuf:"bytes,1,opt,name=volume,proto3" json:"volume,omitempty"` +} + +func (x *VolumesInspectResponse) Reset() { + *x = VolumesInspectResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_protos_volumes_v1_volumes_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *VolumesInspectResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VolumesInspectResponse) ProtoMessage() {} + +func (x *VolumesInspectResponse) ProtoReflect() protoreflect.Message { + mi := &file_protos_volumes_v1_volumes_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VolumesInspectResponse.ProtoReflect.Descriptor instead. +func (*VolumesInspectResponse) Descriptor() ([]byte, []int) { + return file_protos_volumes_v1_volumes_proto_rawDescGZIP(), []int{9} +} + +func (x *VolumesInspectResponse) GetVolume() *Volume { + if x != nil { + return x.Volume + } + return nil +} + var File_protos_volumes_v1_volumes_proto protoreflect.FileDescriptor var file_protos_volumes_v1_volumes_proto_rawDesc = []byte{ @@ -480,36 +574,53 @@ var file_protos_volumes_v1_volumes_proto_rawDesc = []byte{ 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x8b, 0x03, - 0x0a, 0x07, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x12, 0x80, 0x01, 0x0a, 0x0d, 0x56, 0x6f, - 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x36, 0x2e, 0x63, 0x6f, - 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x73, 0x2e, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, - 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x0a, + 0x15, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x5a, 0x0a, 0x16, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, + 0x73, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x40, 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, + 0x6d, 0x65, 0x32, 0x91, 0x04, 0x0a, 0x07, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x12, 0x80, + 0x01, 0x0a, 0x0d, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x12, 0x36, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, + 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, + 0x2e, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, + 0x6d, 0x65, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x7a, 0x0a, 0x0b, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, + 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, + 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x76, + 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, + 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, + 0x0a, 0x0d, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, + 0x36, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x2e, + 0x76, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, + 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, + 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, + 0x65, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x83, 0x01, 0x0a, 0x0e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x49, 0x6e, 0x73, 0x70, + 0x65, 0x63, 0x74, 0x12, 0x37, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x76, 0x6f, 0x6c, 0x75, - 0x6d, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x0b, - 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x34, 0x2e, 0x63, 0x6f, - 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x73, 0x2e, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, - 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, - 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x0d, 0x56, 0x6f, 0x6c, - 0x75, 0x6d, 0x65, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x36, 0x2e, 0x63, 0x6f, 0x6d, - 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x73, 0x2e, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, - 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x76, 0x6f, 0x6c, 0x75, 0x6d, - 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x34, 0x5a, 0x32, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, - 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x73, 0x2f, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x76, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6d, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x49, 0x6e, + 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, + 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, + 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x70, + 0x6f, 0x73, 0x65, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x76, + 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -524,7 +635,7 @@ func file_protos_volumes_v1_volumes_proto_rawDescGZIP() []byte { return file_protos_volumes_v1_volumes_proto_rawDescData } -var file_protos_volumes_v1_volumes_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_protos_volumes_v1_volumes_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_protos_volumes_v1_volumes_proto_goTypes = []interface{}{ (*Volume)(nil), // 0: com.docker.api.protos.volumes.v1.Volume (*AciVolumeCreateOptions)(nil), // 1: com.docker.api.protos.volumes.v1.AciVolumeCreateOptions @@ -534,22 +645,27 @@ var file_protos_volumes_v1_volumes_proto_goTypes = []interface{}{ (*VolumesListResponse)(nil), // 5: com.docker.api.protos.volumes.v1.VolumesListResponse (*VolumesDeleteRequest)(nil), // 6: com.docker.api.protos.volumes.v1.VolumesDeleteRequest (*VolumesDeleteResponse)(nil), // 7: com.docker.api.protos.volumes.v1.VolumesDeleteResponse + (*VolumesInspectRequest)(nil), // 8: com.docker.api.protos.volumes.v1.VolumesInspectRequest + (*VolumesInspectResponse)(nil), // 9: com.docker.api.protos.volumes.v1.VolumesInspectResponse } var file_protos_volumes_v1_volumes_proto_depIdxs = []int32{ 1, // 0: com.docker.api.protos.volumes.v1.VolumesCreateRequest.aci_option:type_name -> com.docker.api.protos.volumes.v1.AciVolumeCreateOptions 0, // 1: com.docker.api.protos.volumes.v1.VolumesCreateResponse.volume:type_name -> com.docker.api.protos.volumes.v1.Volume 0, // 2: com.docker.api.protos.volumes.v1.VolumesListResponse.volumes:type_name -> com.docker.api.protos.volumes.v1.Volume - 2, // 3: com.docker.api.protos.volumes.v1.Volumes.VolumesCreate:input_type -> com.docker.api.protos.volumes.v1.VolumesCreateRequest - 4, // 4: com.docker.api.protos.volumes.v1.Volumes.VolumesList:input_type -> com.docker.api.protos.volumes.v1.VolumesListRequest - 6, // 5: com.docker.api.protos.volumes.v1.Volumes.VolumesDelete:input_type -> com.docker.api.protos.volumes.v1.VolumesDeleteRequest - 3, // 6: com.docker.api.protos.volumes.v1.Volumes.VolumesCreate:output_type -> com.docker.api.protos.volumes.v1.VolumesCreateResponse - 5, // 7: com.docker.api.protos.volumes.v1.Volumes.VolumesList:output_type -> com.docker.api.protos.volumes.v1.VolumesListResponse - 7, // 8: com.docker.api.protos.volumes.v1.Volumes.VolumesDelete:output_type -> com.docker.api.protos.volumes.v1.VolumesDeleteResponse - 6, // [6:9] is the sub-list for method output_type - 3, // [3:6] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 0, // 3: com.docker.api.protos.volumes.v1.VolumesInspectResponse.volume:type_name -> com.docker.api.protos.volumes.v1.Volume + 2, // 4: com.docker.api.protos.volumes.v1.Volumes.VolumesCreate:input_type -> com.docker.api.protos.volumes.v1.VolumesCreateRequest + 4, // 5: com.docker.api.protos.volumes.v1.Volumes.VolumesList:input_type -> com.docker.api.protos.volumes.v1.VolumesListRequest + 6, // 6: com.docker.api.protos.volumes.v1.Volumes.VolumesDelete:input_type -> com.docker.api.protos.volumes.v1.VolumesDeleteRequest + 8, // 7: com.docker.api.protos.volumes.v1.Volumes.VolumesInspect:input_type -> com.docker.api.protos.volumes.v1.VolumesInspectRequest + 3, // 8: com.docker.api.protos.volumes.v1.Volumes.VolumesCreate:output_type -> com.docker.api.protos.volumes.v1.VolumesCreateResponse + 5, // 9: com.docker.api.protos.volumes.v1.Volumes.VolumesList:output_type -> com.docker.api.protos.volumes.v1.VolumesListResponse + 7, // 10: com.docker.api.protos.volumes.v1.Volumes.VolumesDelete:output_type -> com.docker.api.protos.volumes.v1.VolumesDeleteResponse + 9, // 11: com.docker.api.protos.volumes.v1.Volumes.VolumesInspect:output_type -> com.docker.api.protos.volumes.v1.VolumesInspectResponse + 8, // [8:12] is the sub-list for method output_type + 4, // [4:8] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name } func init() { file_protos_volumes_v1_volumes_proto_init() } @@ -654,6 +770,30 @@ func file_protos_volumes_v1_volumes_proto_init() { return nil } } + file_protos_volumes_v1_volumes_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*VolumesInspectRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_protos_volumes_v1_volumes_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*VolumesInspectResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_protos_volumes_v1_volumes_proto_msgTypes[2].OneofWrappers = []interface{}{ (*VolumesCreateRequest_AciOption)(nil), @@ -664,7 +804,7 @@ func file_protos_volumes_v1_volumes_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_protos_volumes_v1_volumes_proto_rawDesc, NumEnums: 0, - NumMessages: 8, + NumMessages: 10, NumExtensions: 0, NumServices: 1, }, @@ -693,6 +833,7 @@ type VolumesClient interface { VolumesCreate(ctx context.Context, in *VolumesCreateRequest, opts ...grpc.CallOption) (*VolumesCreateResponse, error) VolumesList(ctx context.Context, in *VolumesListRequest, opts ...grpc.CallOption) (*VolumesListResponse, error) VolumesDelete(ctx context.Context, in *VolumesDeleteRequest, opts ...grpc.CallOption) (*VolumesDeleteResponse, error) + VolumesInspect(ctx context.Context, in *VolumesInspectRequest, opts ...grpc.CallOption) (*VolumesInspectResponse, error) } type volumesClient struct { @@ -730,11 +871,21 @@ func (c *volumesClient) VolumesDelete(ctx context.Context, in *VolumesDeleteRequ return out, nil } +func (c *volumesClient) VolumesInspect(ctx context.Context, in *VolumesInspectRequest, opts ...grpc.CallOption) (*VolumesInspectResponse, error) { + out := new(VolumesInspectResponse) + err := c.cc.Invoke(ctx, "/com.docker.api.protos.volumes.v1.Volumes/VolumesInspect", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // VolumesServer is the server API for Volumes service. type VolumesServer interface { VolumesCreate(context.Context, *VolumesCreateRequest) (*VolumesCreateResponse, error) VolumesList(context.Context, *VolumesListRequest) (*VolumesListResponse, error) VolumesDelete(context.Context, *VolumesDeleteRequest) (*VolumesDeleteResponse, error) + VolumesInspect(context.Context, *VolumesInspectRequest) (*VolumesInspectResponse, error) } // UnimplementedVolumesServer can be embedded to have forward compatible implementations. @@ -750,6 +901,9 @@ func (*UnimplementedVolumesServer) VolumesList(context.Context, *VolumesListRequ func (*UnimplementedVolumesServer) VolumesDelete(context.Context, *VolumesDeleteRequest) (*VolumesDeleteResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method VolumesDelete not implemented") } +func (*UnimplementedVolumesServer) VolumesInspect(context.Context, *VolumesInspectRequest) (*VolumesInspectResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VolumesInspect not implemented") +} func RegisterVolumesServer(s *grpc.Server, srv VolumesServer) { s.RegisterService(&_Volumes_serviceDesc, srv) @@ -809,6 +963,24 @@ func _Volumes_VolumesDelete_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _Volumes_VolumesInspect_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(VolumesInspectRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VolumesServer).VolumesInspect(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/com.docker.api.protos.volumes.v1.Volumes/VolumesInspect", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VolumesServer).VolumesInspect(ctx, req.(*VolumesInspectRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Volumes_serviceDesc = grpc.ServiceDesc{ ServiceName: "com.docker.api.protos.volumes.v1.Volumes", HandlerType: (*VolumesServer)(nil), @@ -825,6 +997,10 @@ var _Volumes_serviceDesc = grpc.ServiceDesc{ MethodName: "VolumesDelete", Handler: _Volumes_VolumesDelete_Handler, }, + { + MethodName: "VolumesInspect", + Handler: _Volumes_VolumesInspect_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "protos/volumes/v1/volumes.proto", diff --git a/protos/volumes/v1/volumes.proto b/protos/volumes/v1/volumes.proto index 4383131e2..6ae22e293 100644 --- a/protos/volumes/v1/volumes.proto +++ b/protos/volumes/v1/volumes.proto @@ -25,6 +25,7 @@ service Volumes { rpc VolumesCreate(VolumesCreateRequest) returns (VolumesCreateResponse); rpc VolumesList(VolumesListRequest) returns (VolumesListResponse); rpc VolumesDelete(VolumesDeleteRequest) returns (VolumesDeleteResponse); + rpc VolumesInspect(VolumesInspectRequest) returns (VolumesInspectResponse); } message Volume { @@ -60,3 +61,11 @@ message VolumesDeleteRequest { message VolumesDeleteResponse { } + +message VolumesInspectRequest { + string id = 1; +} + +message VolumesInspectResponse { + Volume volume = 1; +} diff --git a/server/metrics.go b/server/metrics.go index a1f871b4e..b465981f1 100644 --- a/server/metrics.go +++ b/server/metrics.go @@ -27,21 +27,22 @@ import ( var ( methodMapping = map[string]string{ - "/com.docker.api.protos.containers.v1.Containers/List": "ps", - "/com.docker.api.protos.containers.v1.Containers/Start": "start", - "/com.docker.api.protos.containers.v1.Containers/Stop": "stop", - "/com.docker.api.protos.containers.v1.Containers/Run": "run", - "/com.docker.api.protos.containers.v1.Containers/Exec": "exec", - "/com.docker.api.protos.containers.v1.Containers/Delete": "rm", - "/com.docker.api.protos.containers.v1.Containers/Kill": "kill", - "/com.docker.api.protos.containers.v1.Containers/Inspect": "inspect", - "/com.docker.api.protos.containers.v1.Containers/Logs": "logs", - "/com.docker.api.protos.streams.v1.Streaming/NewStream": "streaming", - "/com.docker.api.protos.context.v1.Contexts/List": "context ls", - "/com.docker.api.protos.context.v1.Contexts/SetCurrent": "context use", - "/com.docker.api.protos.volumes.v1.Volumes/VolumesList": "volume ls", - "/com.docker.api.protos.volumes.v1.Volumes/VolumesDelete": "volume rm", - "/com.docker.api.protos.volumes.v1.Volumes/VolumesCreate": "volume create", + "/com.docker.api.protos.containers.v1.Containers/List": "ps", + "/com.docker.api.protos.containers.v1.Containers/Start": "start", + "/com.docker.api.protos.containers.v1.Containers/Stop": "stop", + "/com.docker.api.protos.containers.v1.Containers/Run": "run", + "/com.docker.api.protos.containers.v1.Containers/Exec": "exec", + "/com.docker.api.protos.containers.v1.Containers/Delete": "rm", + "/com.docker.api.protos.containers.v1.Containers/Kill": "kill", + "/com.docker.api.protos.containers.v1.Containers/Inspect": "inspect", + "/com.docker.api.protos.containers.v1.Containers/Logs": "logs", + "/com.docker.api.protos.streams.v1.Streaming/NewStream": "streaming", + "/com.docker.api.protos.context.v1.Contexts/List": "context ls", + "/com.docker.api.protos.context.v1.Contexts/SetCurrent": "context use", + "/com.docker.api.protos.volumes.v1.Volumes/VolumesList": "volume ls", + "/com.docker.api.protos.volumes.v1.Volumes/VolumesDelete": "volume rm", + "/com.docker.api.protos.volumes.v1.Volumes/VolumesCreate": "volume create", + "/com.docker.api.protos.volumes.v1.Volumes/VolumesInspect": "volume inspect", } ) diff --git a/server/proxy/volumes.go b/server/proxy/volumes.go index 0d2ce4efc..6da274322 100644 --- a/server/proxy/volumes.go +++ b/server/proxy/volumes.go @@ -63,6 +63,14 @@ func (p *proxy) VolumesDelete(ctx context.Context, req *volumesv1.VolumesDeleteR return &volumesv1.VolumesDeleteResponse{}, err } +// VolumesInspect inspects a volume. +func (p *proxy) VolumesInspect(ctx context.Context, req *volumesv1.VolumesInspectRequest) (*volumesv1.VolumesInspectResponse, error) { + v, err := Client(ctx).VolumeService().Inspect(ctx, req.Id) + return &volumesv1.VolumesInspectResponse{ + Volume: toGrpcVolume(v), + }, err +} + func toGrpcVolumeList(volumeList []volumes.Volume) []*volumesv1.Volume { var ret []*volumesv1.Volume for _, v := range volumeList { diff --git a/tests/aci-e2e/e2e-aci_test.go b/tests/aci-e2e/e2e-aci_test.go index 665d7e631..198cba625 100644 --- a/tests/aci-e2e/e2e-aci_test.go +++ b/tests/aci-e2e/e2e-aci_test.go @@ -145,7 +145,10 @@ func uploadTestFile(t *testing.T, aciContext store.AciContext, accountName strin uploadFile(t, *cred, u.String(), testFileName, testFileContent) } -const fileshareName = "dockertestshare" +const ( + fileshareName = "dockertestshare" + fileshareName2 = "dockertestshare2" +) func TestRunVolume(t *testing.T) { const ( @@ -203,9 +206,9 @@ func TestRunVolume(t *testing.T) { }) t.Run("create second fileshare", func(t *testing.T) { - c.RunDockerCmd("volume", "create", "--storage-account", accountName, "dockertestshare2") + c.RunDockerCmd("volume", "create", "--storage-account", accountName, fileshareName2) }) - volumeID2 := accountName + "/dockertestshare2" + volumeID2 := accountName + "/" + fileshareName2 t.Run("list volumes", func(t *testing.T) { res := c.RunDockerCmd("volume", "ls", "--quiet") @@ -225,12 +228,27 @@ func TestRunVolume(t *testing.T) { assert.Equal(t, fields[0], volumeID2) }) + t.Run("inspect volumes", func(t *testing.T) { + res := c.RunDockerCmd("volume", "inspect", volumeID) + assert.Equal(t, res.Stdout(), fmt.Sprintf(`{ + "ID": %q, + "Description": "Fileshare %s in %s storage account" +} +`, volumeID, fileshareName, accountName)) + res = c.RunDockerCmd("volume", "inspect", volumeID2) + assert.Equal(t, res.Stdout(), fmt.Sprintf(`{ + "ID": %q, + "Description": "Fileshare %s in %s storage account" +} +`, volumeID2, fileshareName2, accountName)) + }) + t.Run("delete only fileshare", func(t *testing.T) { c.RunDockerCmd("volume", "rm", volumeID2) res := c.RunDockerCmd("volume", "ls") lines := lines(res.Stdout()) assert.Equal(t, len(lines), 2) - assert.Assert(t, !strings.Contains(res.Stdout(), "dockertestshare2"), "second fileshare still visible after rm") + assert.Assert(t, !strings.Contains(res.Stdout(), fileshareName2), "second fileshare still visible after rm") }) t.Run("upload file", func(t *testing.T) {