diff --git a/cmd/tink-cli/cmd/hardware/all.go b/cmd/tink-cli/cmd/hardware/all.go index 76c847941..84c25e3e8 100644 --- a/cmd/tink-cli/cmd/hardware/all.go +++ b/cmd/tink-cli/cmd/hardware/all.go @@ -14,7 +14,7 @@ import ( // allCmd represents the all command var allCmd = &cobra.Command{ Use: "all", - Short: "Get all known hardware for facility", + Short: "get all known hardware for facility", Run: func(cmd *cobra.Command, args []string) { alls, err := client.HardwareClient.All(context.Background(), &hardware.Empty{}) if err != nil { diff --git a/cmd/tink-cli/cmd/hardware/delete.go b/cmd/tink-cli/cmd/hardware/delete.go new file mode 100644 index 000000000..45abe39cd --- /dev/null +++ b/cmd/tink-cli/cmd/hardware/delete.go @@ -0,0 +1,35 @@ +// Copyright © 2018 packet.net + +package hardware + +import ( + "context" + "log" + + "github.com/spf13/cobra" + "github.com/tinkerbell/tink/client" + "github.com/tinkerbell/tink/protos/hardware" +) + +// deleteCmd represents the id command +var deleteCmd = &cobra.Command{ + Use: "delete", + Short: "delete hardware by id", + Example: "tink hardware delete 224ee6ab-ad62-4070-a900-ed816444cec0 cb76ae54-93e9-401c-a5b2-d455bb3800b1", + Args: func(_ *cobra.Command, args []string) error { + return verifyUUIDs(args) + }, + Run: func(cmd *cobra.Command, args []string) { + for _, id := range args { + _, err := client.HardwareClient.Delete(context.Background(), &hardware.DeleteRequest{ID: id}) + if err != nil { + log.Fatal(err) + } + log.Println("hardware data with id", id, "deleted successfully") + } + }, +} + +func init() { + SubCommands = append(SubCommands, deleteCmd) +} diff --git a/cmd/tink-cli/cmd/hardware/id.go b/cmd/tink-cli/cmd/hardware/id.go index 053d81611..2bb0cff5f 100644 --- a/cmd/tink-cli/cmd/hardware/id.go +++ b/cmd/tink-cli/cmd/hardware/id.go @@ -15,7 +15,7 @@ import ( // idCmd represents the id command var idCmd = &cobra.Command{ Use: "id", - Short: "Get hardware by id", + Short: "get hardware by id", Example: "tink hardware id 224ee6ab-ad62-4070-a900-ed816444cec0 cb76ae54-93e9-401c-a5b2-d455bb3800b1", Args: func(_ *cobra.Command, args []string) error { return verifyUUIDs(args) diff --git a/cmd/tink-cli/cmd/hardware/ip.go b/cmd/tink-cli/cmd/hardware/ip.go index 911b32f4e..fc6727a4a 100644 --- a/cmd/tink-cli/cmd/hardware/ip.go +++ b/cmd/tink-cli/cmd/hardware/ip.go @@ -16,7 +16,7 @@ import ( // ipCmd represents the ip command var ipCmd = &cobra.Command{ Use: "ip", - Short: "Get hardware by any associated ip", + Short: "get hardware by any associated ip", Example: "tink hardware ip 10.0.0.2 10.0.0.3", Args: func(_ *cobra.Command, args []string) error { for _, arg := range args { diff --git a/cmd/tink-cli/cmd/hardware/mac.go b/cmd/tink-cli/cmd/hardware/mac.go index 74a43a120..794798b0c 100644 --- a/cmd/tink-cli/cmd/hardware/mac.go +++ b/cmd/tink-cli/cmd/hardware/mac.go @@ -16,7 +16,7 @@ import ( // macCmd represents the mac command var macCmd = &cobra.Command{ Use: "mac", - Short: "Get hardware by any associated mac", + Short: "get hardware by any associated mac", Example: "tink hardware mac 00:00:00:00:00:01 00:00:00:00:00:02", Args: func(_ *cobra.Command, args []string) error { for _, arg := range args { diff --git a/cmd/tink-cli/cmd/hardware/push.go b/cmd/tink-cli/cmd/hardware/push.go index da803a788..dc26d2864 100644 --- a/cmd/tink-cli/cmd/hardware/push.go +++ b/cmd/tink-cli/cmd/hardware/push.go @@ -24,7 +24,7 @@ var ( // pushCmd represents the push command var pushCmd = &cobra.Command{ Use: "push", - Short: "Push new hardware to tinkerbell", + Short: "push new hardware to tinkerbell", Example: `cat /tmp/data.json | tink hardware push tink hardware push --file /tmp/data.json`, PreRunE: func(c *cobra.Command, args []string) error { diff --git a/cmd/tink-cli/cmd/hardware/watch.go b/cmd/tink-cli/cmd/hardware/watch.go index d06ec2ff2..ebef8dfbd 100644 --- a/cmd/tink-cli/cmd/hardware/watch.go +++ b/cmd/tink-cli/cmd/hardware/watch.go @@ -17,7 +17,7 @@ import ( // watchCmd represents the watch command var watchCmd = &cobra.Command{ Use: "watch", - Short: "Register to watch an id for any changes", + Short: "register to watch an id for any changes", Example: "tink hardware watch 224ee6ab-ad62-4070-a900-ed816444cec0 cb76ae54-93e9-401c-a5b2-d455bb3800b1", Args: func(_ *cobra.Command, args []string) error { return verifyUUIDs(args) diff --git a/grpc-server/hardware.go b/grpc-server/hardware.go index a4b343b25..f461f0ee2 100644 --- a/grpc-server/hardware.go +++ b/grpc-server/hardware.go @@ -244,3 +244,57 @@ func (s *server) Cert() []byte { func (s *server) ModTime() time.Time { return s.modT } + +func (s *server) Delete(ctx context.Context, in *hardware.DeleteRequest) (*hardware.Empty, error) { + logger.Info("delete") + labels := prometheus.Labels{"method": "Delete", "op": ""} + metrics.CacheInFlight.With(labels).Inc() + defer metrics.CacheInFlight.With(labels).Dec() + + // must be a copy so deferred cacheInFlight.Dec matches the Inc + labels = prometheus.Labels{"method": "Delete", "op": ""} + + if in.ID == "" { + metrics.CacheTotals.With(labels).Inc() + metrics.CacheErrors.With(labels).Inc() + err := errors.New("id must be set to a UUID") + logger.Error(err) + return &hardware.Empty{}, err + } + + logger.With("id", in.ID).Info("data deleted") + + var fn func() error + labels["op"] = "delete" + msg := "deleting into DB" + fn = func() error { return db.DeleteFromDB(ctx, s.db, in.ID) } + + metrics.CacheTotals.With(labels).Inc() + timer := prometheus.NewTimer(metrics.CacheDuration.With(labels)) + defer timer.ObserveDuration() + + logger.Info(msg) + err := fn() + logger.Info("done " + msg) + if err != nil { + metrics.CacheErrors.With(labels).Inc() + l := logger + if pqErr := db.Error(err); pqErr != nil { + l = l.With("detail", pqErr.Detail, "where", pqErr.Where) + } + l.Error(err) + } + + s.watchLock.RLock() + if ch := s.watch[in.ID]; ch != nil { + select { + case ch <- in.ID: + default: + metrics.WatchMissTotal.Inc() + logger.With("id", in.ID).Info("skipping blocked watcher") + } + } + s.watchLock.RUnlock() + + return &hardware.Empty{}, err +} diff --git a/protos/hardware/hardware.pb.go b/protos/hardware/hardware.pb.go index c5fbb1a7a..64b0cf966 100644 --- a/protos/hardware/hardware.pb.go +++ b/protos/hardware/hardware.pb.go @@ -6,11 +6,12 @@ package hardware import ( context "context" fmt "fmt" + math "math" + proto "github.com/golang/protobuf/proto" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - math "math" ) // Reference imports to suppress errors if they are not otherwise used. @@ -188,36 +189,78 @@ func (m *Hardware) GetJSON() string { return "" } +type DeleteRequest struct { + ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } +func (m *DeleteRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteRequest) ProtoMessage() {} +func (*DeleteRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_61ac56d7fc2e671f, []int{4} +} + +func (m *DeleteRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DeleteRequest.Unmarshal(m, b) +} +func (m *DeleteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DeleteRequest.Marshal(b, m, deterministic) +} +func (m *DeleteRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_DeleteRequest.Merge(m, src) +} +func (m *DeleteRequest) XXX_Size() int { + return xxx_messageInfo_DeleteRequest.Size(m) +} +func (m *DeleteRequest) XXX_DiscardUnknown() { + xxx_messageInfo_DeleteRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_DeleteRequest proto.InternalMessageInfo + +func (m *DeleteRequest) GetID() string { + if m != nil { + return m.ID + } + return "" +} + func init() { proto.RegisterType((*PushRequest)(nil), "github.com.tinkerbell.tink.protos.hardware.PushRequest") proto.RegisterType((*Empty)(nil), "github.com.tinkerbell.tink.protos.hardware.Empty") proto.RegisterType((*GetRequest)(nil), "github.com.tinkerbell.tink.protos.hardware.GetRequest") proto.RegisterType((*Hardware)(nil), "github.com.tinkerbell.tink.protos.hardware.Hardware") + proto.RegisterType((*DeleteRequest)(nil), "github.com.tinkerbell.tink.protos.hardware.DeleteRequest") } func init() { proto.RegisterFile("hardware/hardware.proto", fileDescriptor_61ac56d7fc2e671f) } var fileDescriptor_61ac56d7fc2e671f = []byte{ - // 294 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcf, 0x48, 0x2c, 0x4a, - 0x29, 0x4f, 0x2c, 0x4a, 0xd5, 0x87, 0x31, 0xf4, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, 0x85, 0xb4, 0xd2, - 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0x4a, 0x32, 0xf3, 0xb2, 0x53, 0x8b, - 0x92, 0x52, 0x73, 0x72, 0xc0, 0x4c, 0x88, 0x8a, 0x62, 0x3d, 0x98, 0x0e, 0x25, 0x45, 0x2e, 0xee, - 0x80, 0xd2, 0xe2, 0x8c, 0xa0, 0xd4, 0xc2, 0xd2, 0xd4, 0xe2, 0x12, 0x21, 0x21, 0x2e, 0x96, 0x94, - 0xc4, 0x92, 0x44, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x30, 0x5b, 0x89, 0x9d, 0x8b, 0xd5, - 0x35, 0xb7, 0xa0, 0xa4, 0x52, 0xc9, 0x8e, 0x8b, 0xcb, 0x3d, 0xb5, 0x04, 0xa6, 0x54, 0x80, 0x8b, - 0xd9, 0xd7, 0xd1, 0x19, 0xaa, 0x12, 0xc4, 0x14, 0xe2, 0xe3, 0x62, 0xf2, 0x0c, 0x90, 0x60, 0x02, - 0x0b, 0x30, 0x79, 0x06, 0x80, 0xf9, 0x2e, 0x12, 0xcc, 0x50, 0xbe, 0x8b, 0x92, 0x1c, 0x17, 0x87, - 0x07, 0xd4, 0x5e, 0x90, 0x45, 0x5e, 0xc1, 0xfe, 0x7e, 0x30, 0x8b, 0x40, 0x6c, 0xa3, 0xc3, 0x6c, - 0x5c, 0xfc, 0x30, 0x05, 0xc1, 0xa9, 0x45, 0x65, 0x99, 0xc9, 0xa9, 0x42, 0x45, 0x5c, 0x2c, 0x20, - 0xf7, 0x09, 0x99, 0xeb, 0x11, 0xef, 0x29, 0x3d, 0x24, 0x1f, 0x49, 0x19, 0x92, 0xa2, 0x11, 0xec, - 0x4f, 0xa1, 0x52, 0x2e, 0x56, 0xa7, 0x4a, 0x90, 0x87, 0xcc, 0x48, 0xd1, 0x8b, 0x08, 0x1a, 0x29, - 0x13, 0x52, 0xf4, 0xc1, 0x83, 0xa4, 0x84, 0x8b, 0xc5, 0xa9, 0xd2, 0x33, 0x60, 0x40, 0x6c, 0x75, - 0xa1, 0xb3, 0xad, 0x05, 0x5c, 0xcc, 0x8e, 0x39, 0x39, 0x42, 0xa4, 0x47, 0x0e, 0x79, 0xf6, 0x19, - 0x30, 0x0a, 0xe5, 0x71, 0xb1, 0x79, 0xe6, 0xa5, 0x83, 0x12, 0x2e, 0x19, 0x96, 0x92, 0x91, 0x88, - 0xca, 0xb9, 0x58, 0xc3, 0x13, 0x4b, 0x92, 0x33, 0xe8, 0x1b, 0xb0, 0x06, 0x8c, 0x4e, 0x5c, 0x51, - 0x1c, 0x30, 0xe1, 0x24, 0x36, 0xb0, 0x3a, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x08, 0x70, - 0x0f, 0x65, 0x2b, 0x04, 0x00, 0x00, + // 326 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x93, 0x4b, 0x4f, 0x83, 0x40, + 0x14, 0x85, 0x43, 0x0b, 0xb4, 0x5e, 0xe3, 0x23, 0xb3, 0x91, 0x74, 0xe1, 0x83, 0x95, 0x71, 0x31, + 0xd6, 0x47, 0x34, 0x6e, 0x4c, 0x8a, 0x18, 0xc5, 0x44, 0x25, 0xed, 0xc2, 0xc4, 0x1d, 0xd0, 0x49, + 0x21, 0x52, 0xc0, 0x61, 0x68, 0xc3, 0x6f, 0xf3, 0xcf, 0x99, 0x19, 0x18, 0x1f, 0x3b, 0x61, 0x51, + 0x77, 0x67, 0x26, 0xf7, 0xde, 0x2f, 0xe7, 0xcc, 0x5c, 0xd8, 0x09, 0x3d, 0x3a, 0x5d, 0x7a, 0x94, + 0x1c, 0x4b, 0x81, 0x33, 0x9a, 0xb2, 0x14, 0x1d, 0xcd, 0x22, 0x16, 0x16, 0x3e, 0x0e, 0xd2, 0x39, + 0x66, 0x51, 0xf2, 0x46, 0xa8, 0x4f, 0xe2, 0x58, 0xc8, 0xaa, 0x22, 0xc7, 0xb2, 0xc3, 0x3c, 0x80, + 0x75, 0xb7, 0xc8, 0xc3, 0x31, 0x79, 0x2f, 0x48, 0xce, 0x10, 0x02, 0x75, 0xea, 0x31, 0xcf, 0x50, + 0xf6, 0x95, 0xc3, 0xb5, 0xb1, 0xd0, 0x66, 0x0f, 0xb4, 0xdb, 0x79, 0xc6, 0x4a, 0xf3, 0x1a, 0xe0, + 0x8e, 0x30, 0x59, 0xba, 0x0d, 0xdd, 0xc7, 0xd1, 0x4d, 0x5d, 0xc9, 0x25, 0xda, 0x84, 0x8e, 0xe3, + 0x1a, 0x1d, 0x71, 0xd1, 0x71, 0x5c, 0x71, 0xb6, 0x8d, 0x6e, 0x7d, 0xb6, 0xcd, 0x5d, 0xe8, 0xdf, + 0xd7, 0x5c, 0x0e, 0x7a, 0x98, 0x3c, 0x3f, 0x49, 0x10, 0xd7, 0xe6, 0x1e, 0x6c, 0xd8, 0x24, 0x26, + 0x8c, 0x48, 0x44, 0x35, 0x40, 0x91, 0x03, 0x4e, 0x3f, 0x7a, 0xb0, 0x25, 0x27, 0x4c, 0x08, 0x5d, + 0x44, 0x01, 0x41, 0x14, 0x54, 0x6e, 0x00, 0x5d, 0xe2, 0xbf, 0xbb, 0xc6, 0x3f, 0x2c, 0x0f, 0x4e, + 0x9a, 0x34, 0x8a, 0x20, 0x50, 0x01, 0x9a, 0x55, 0x72, 0xc7, 0x17, 0x4d, 0x7a, 0xbf, 0xb3, 0x1b, + 0x9c, 0x37, 0xe9, 0xfb, 0xca, 0x8c, 0x81, 0x6a, 0x95, 0x8e, 0xfb, 0x2f, 0x54, 0x7b, 0xc5, 0xd4, + 0x0c, 0xba, 0xa3, 0x38, 0x46, 0xcd, 0x1f, 0xa7, 0x1d, 0x6f, 0xa8, 0xa0, 0x04, 0x74, 0x27, 0x99, + 0xf1, 0x6f, 0xd7, 0x02, 0xda, 0xe2, 0x13, 0x2d, 0x41, 0x7b, 0xf1, 0x58, 0x10, 0xae, 0x36, 0xd8, + 0xa1, 0x82, 0x16, 0xa0, 0x57, 0x6b, 0x86, 0xae, 0x9a, 0x4c, 0xf8, 0xb5, 0x9a, 0x2d, 0x0c, 0x5b, + 0xf0, 0xda, 0x97, 0x37, 0xbe, 0x2e, 0x4a, 0xce, 0x3e, 0x03, 0x00, 0x00, 0xff, 0xff, 0xd0, 0xaf, + 0xef, 0x64, 0xc4, 0x04, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -239,6 +282,7 @@ type HardwareServiceClient interface { All(ctx context.Context, in *Empty, opts ...grpc.CallOption) (HardwareService_AllClient, error) Ingest(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) Watch(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (HardwareService_WatchClient, error) + Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*Empty, error) } type hardwareServiceClient struct { @@ -358,6 +402,15 @@ func (x *hardwareServiceWatchClient) Recv() (*Hardware, error) { return m, nil } +func (c *hardwareServiceClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := c.cc.Invoke(ctx, "/github.com.tinkerbell.tink.protos.hardware.HardwareService/Delete", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // HardwareServiceServer is the server API for HardwareService service. type HardwareServiceServer interface { Push(context.Context, *PushRequest) (*Empty, error) @@ -367,6 +420,7 @@ type HardwareServiceServer interface { All(*Empty, HardwareService_AllServer) error Ingest(context.Context, *Empty) (*Empty, error) Watch(*GetRequest, HardwareService_WatchServer) error + Delete(context.Context, *DeleteRequest) (*Empty, error) } // UnimplementedHardwareServiceServer can be embedded to have forward compatible implementations. @@ -394,6 +448,9 @@ func (*UnimplementedHardwareServiceServer) Ingest(ctx context.Context, req *Empt func (*UnimplementedHardwareServiceServer) Watch(req *GetRequest, srv HardwareService_WatchServer) error { return status.Errorf(codes.Unimplemented, "method Watch not implemented") } +func (*UnimplementedHardwareServiceServer) Delete(ctx context.Context, req *DeleteRequest) (*Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented") +} func RegisterHardwareServiceServer(s *grpc.Server, srv HardwareServiceServer) { s.RegisterService(&_HardwareService_serviceDesc, srv) @@ -531,6 +588,24 @@ func (x *hardwareServiceWatchServer) Send(m *Hardware) error { return x.ServerStream.SendMsg(m) } +func _HardwareService_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(HardwareServiceServer).Delete(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/github.com.tinkerbell.tink.protos.hardware.HardwareService/Delete", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HardwareServiceServer).Delete(ctx, req.(*DeleteRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _HardwareService_serviceDesc = grpc.ServiceDesc{ ServiceName: "github.com.tinkerbell.tink.protos.hardware.HardwareService", HandlerType: (*HardwareServiceServer)(nil), @@ -555,6 +630,10 @@ var _HardwareService_serviceDesc = grpc.ServiceDesc{ MethodName: "Ingest", Handler: _HardwareService_Ingest_Handler, }, + { + MethodName: "Delete", + Handler: _HardwareService_Delete_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/protos/hardware/hardware.proto b/protos/hardware/hardware.proto index 47fc95d09..d8c63076f 100644 --- a/protos/hardware/hardware.proto +++ b/protos/hardware/hardware.proto @@ -12,6 +12,7 @@ service HardwareService { rpc All(Empty) returns (stream Hardware); rpc Ingest(Empty) returns (Empty); rpc Watch(GetRequest) returns (stream Hardware); + rpc Delete(DeleteRequest) returns (Empty); } message PushRequest { @@ -30,3 +31,7 @@ message GetRequest { message Hardware { string JSON = 1; } + +message DeleteRequest { + string ID = 1; +} diff --git a/protos/template/template.pb.go b/protos/template/template.pb.go index a4ce6ad4e..20f4fa3ed 100644 --- a/protos/template/template.pb.go +++ b/protos/template/template.pb.go @@ -6,12 +6,13 @@ package template import ( context "context" fmt "fmt" + math "math" + proto "github.com/golang/protobuf/proto" timestamp "github.com/golang/protobuf/ptypes/timestamp" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/protos/workflow/workflow.pb.go b/protos/workflow/workflow.pb.go index af0033daa..f402e115d 100644 --- a/protos/workflow/workflow.pb.go +++ b/protos/workflow/workflow.pb.go @@ -6,12 +6,13 @@ package workflow import ( context "context" fmt "fmt" + math "math" + proto "github.com/golang/protobuf/proto" timestamp "github.com/golang/protobuf/ptypes/timestamp" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - math "math" ) // Reference imports to suppress errors if they are not otherwise used.