diff --git a/matchbox/cli/generic.go b/matchbox/cli/generic.go new file mode 100644 index 00000000..3ffc21a0 --- /dev/null +++ b/matchbox/cli/generic.go @@ -0,0 +1,16 @@ +package cli + +import ( + "github.com/spf13/cobra" +) + +// genericCmd represents the generic command +var genericCmd = &cobra.Command{ + Use: "generic", + Short: "Manage Generic templates", + Long: `Manage Generic templates`, +} + +func init() { + RootCmd.AddCommand(genericCmd) +} diff --git a/matchbox/cli/generic_create.go b/matchbox/cli/generic_create.go new file mode 100644 index 00000000..68188099 --- /dev/null +++ b/matchbox/cli/generic_create.go @@ -0,0 +1,48 @@ +package cli + +import ( + "io/ioutil" + "path/filepath" + + "context" + "github.com/spf13/cobra" + + pb "github.com/coreos/matchbox/matchbox/server/serverpb" +) + +// genericPutCmd creates and updates Generic templates. +var ( + genericPutCmd = &cobra.Command{ + Use: "create --file FILENAME", + Short: "Create an Generic template", + Long: `Create an Generic template`, + Run: runGenericPutCmd, + } +) + +func init() { + genericCmd.AddCommand(genericPutCmd) + genericPutCmd.Flags().StringVarP(&flagFilename, "filename", "f", "", "filename to use to create an Generic template") + genericPutCmd.MarkFlagRequired("filename") +} + +func runGenericPutCmd(cmd *cobra.Command, args []string) { + if len(flagFilename) == 0 { + cmd.Help() + return + } + if err := validateArgs(cmd, args); err != nil { + return + } + + client := mustClientFromCmd(cmd) + config, err := ioutil.ReadFile(flagFilename) + if err != nil { + exitWithError(ExitError, err) + } + req := &pb.GenericPutRequest{Name: filepath.Base(flagFilename), Config: config} + _, err = client.Generic.GenericPut(context.TODO(), req) + if err != nil { + exitWithError(ExitError, err) + } +} diff --git a/matchbox/client/client.go b/matchbox/client/client.go index 30d8d7d1..c7dc2dbd 100644 --- a/matchbox/client/client.go +++ b/matchbox/client/client.go @@ -31,6 +31,7 @@ type Client struct { Groups rpcpb.GroupsClient Profiles rpcpb.ProfilesClient Ignition rpcpb.IgnitionClient + Generic rpcpb.GenericClient conn *grpc.ClientConn } @@ -57,6 +58,7 @@ func newClient(config *Config) (*Client, error) { Groups: rpcpb.NewGroupsClient(conn), Profiles: rpcpb.NewProfilesClient(conn), Ignition: rpcpb.NewIgnitionClient(conn), + Generic: rpcpb.NewGenericClient(conn), } return client, nil } diff --git a/matchbox/http/generic.go b/matchbox/http/generic.go index 533d78bd..513bd11a 100644 --- a/matchbox/http/generic.go +++ b/matchbox/http/generic.go @@ -35,7 +35,7 @@ func (s *Server) genericHandler(core server.Server) ContextHandler { http.NotFound(w, req) return } - contents, err := core.GenericGet(ctx, profile.GenericId) + contents, err := core.GenericGet(ctx, &pb.GenericGetRequest{Name: profile.GenericId}) if err != nil { s.logger.WithFields(logrus.Fields{ "labels": labelsFromRequest(nil, req), diff --git a/matchbox/http/test_fixtures.go b/matchbox/http/test_fixtures.go index 4de0f323..34122ac8 100644 --- a/matchbox/http/test_fixtures.go +++ b/matchbox/http/test_fixtures.go @@ -12,6 +12,11 @@ var ( IgnitionId: "ignition.yaml", } + testProfileGeneric = &storagepb.Profile{ + Id: "g1h2i3j4", + IgnitionId: "generic.tmpl", + } + testGroupWithMAC = &storagepb.Group{ Id: "test-group", Name: "test group", diff --git a/matchbox/rpc/generic.go b/matchbox/rpc/generic.go new file mode 100644 index 00000000..4e6a47df --- /dev/null +++ b/matchbox/rpc/generic.go @@ -0,0 +1,35 @@ +package rpc + +import ( + "golang.org/x/net/context" + + "github.com/coreos/matchbox/matchbox/rpc/rpcpb" + "github.com/coreos/matchbox/matchbox/server" + pb "github.com/coreos/matchbox/matchbox/server/serverpb" +) + +// genericServer takes a matchbox Server and implements a gRPC GenericServer. +type genericServer struct { + srv server.Server +} + +func newGenericServer(s server.Server) rpcpb.GenericServer { + return &genericServer{ + srv: s, + } +} + +func (s *genericServer) GenericPut(ctx context.Context, req *pb.GenericPutRequest) (*pb.GenericPutResponse, error) { + _, err := s.srv.GenericPut(ctx, req) + return &pb.GenericPutResponse{}, grpcError(err) +} + +func (s *genericServer) GenericGet(ctx context.Context, req *pb.GenericGetRequest) (*pb.GenericGetResponse, error) { + template, err := s.srv.GenericGet(ctx, req) + return &pb.GenericGetResponse{Config: []byte(template)}, grpcError(err) +} + +func (s *genericServer) GenericDelete(ctx context.Context, req *pb.GenericDeleteRequest) (*pb.GenericDeleteResponse, error) { + err := s.srv.GenericDelete(ctx, req) + return &pb.GenericDeleteResponse{}, grpcError(err) +} diff --git a/matchbox/rpc/grpc.go b/matchbox/rpc/grpc.go index d3248ef2..2c23c635 100644 --- a/matchbox/rpc/grpc.go +++ b/matchbox/rpc/grpc.go @@ -23,5 +23,6 @@ func NewServer(s server.Server, tls *tls.Config) *grpc.Server { rpcpb.RegisterProfilesServer(grpcServer, newProfileServer(s)) rpcpb.RegisterSelectServer(grpcServer, newSelectServer(s)) rpcpb.RegisterIgnitionServer(grpcServer, newIgnitionServer(s)) + rpcpb.RegisterGenericServer(grpcServer, newGenericServer(s)) return grpcServer } diff --git a/matchbox/rpc/rpcpb/rpc.pb.go b/matchbox/rpc/rpcpb/rpc.pb.go index b8d5efd9..c2865dcc 100644 --- a/matchbox/rpc/rpcpb/rpc.pb.go +++ b/matchbox/rpc/rpcpb/rpc.pb.go @@ -386,7 +386,7 @@ var _Profiles_serviceDesc = grpc.ServiceDesc{ // Client API for Ignition service type IgnitionClient interface { - // Create or update an Container Linux Config template. + // Create or update a Container Linux Config template. IgnitionPut(ctx context.Context, in *serverpb.IgnitionPutRequest, opts ...grpc.CallOption) (*serverpb.IgnitionPutResponse, error) // Get a Container Linux Config template by name. IgnitionGet(ctx context.Context, in *serverpb.IgnitionGetRequest, opts ...grpc.CallOption) (*serverpb.IgnitionGetResponse, error) @@ -432,7 +432,7 @@ func (c *ignitionClient) IgnitionDelete(ctx context.Context, in *serverpb.Igniti // Server API for Ignition service type IgnitionServer interface { - // Create or update an Container Linux Config template. + // Create or update a Container Linux Config template. IgnitionPut(context.Context, *serverpb.IgnitionPutRequest) (*serverpb.IgnitionPutResponse, error) // Get a Container Linux Config template by name. IgnitionGet(context.Context, *serverpb.IgnitionGetRequest) (*serverpb.IgnitionGetResponse, error) @@ -519,6 +519,142 @@ var _Ignition_serviceDesc = grpc.ServiceDesc{ Metadata: "rpc.proto", } +// Client API for Generic service + +type GenericClient interface { + // Create or update a Generic template. + GenericPut(ctx context.Context, in *serverpb.GenericPutRequest, opts ...grpc.CallOption) (*serverpb.GenericPutResponse, error) + // Get a Generic template by name. + GenericGet(ctx context.Context, in *serverpb.GenericGetRequest, opts ...grpc.CallOption) (*serverpb.GenericGetResponse, error) + // Delete a Generic template by name. + GenericDelete(ctx context.Context, in *serverpb.GenericDeleteRequest, opts ...grpc.CallOption) (*serverpb.GenericDeleteResponse, error) +} + +type genericClient struct { + cc *grpc.ClientConn +} + +func NewGenericClient(cc *grpc.ClientConn) GenericClient { + return &genericClient{cc} +} + +func (c *genericClient) GenericPut(ctx context.Context, in *serverpb.GenericPutRequest, opts ...grpc.CallOption) (*serverpb.GenericPutResponse, error) { + out := new(serverpb.GenericPutResponse) + err := grpc.Invoke(ctx, "/rpcpb.Generic/GenericPut", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *genericClient) GenericGet(ctx context.Context, in *serverpb.GenericGetRequest, opts ...grpc.CallOption) (*serverpb.GenericGetResponse, error) { + out := new(serverpb.GenericGetResponse) + err := grpc.Invoke(ctx, "/rpcpb.Generic/GenericGet", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *genericClient) GenericDelete(ctx context.Context, in *serverpb.GenericDeleteRequest, opts ...grpc.CallOption) (*serverpb.GenericDeleteResponse, error) { + out := new(serverpb.GenericDeleteResponse) + err := grpc.Invoke(ctx, "/rpcpb.Generic/GenericDelete", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Generic service + +type GenericServer interface { + // Create or update a Generic template. + GenericPut(context.Context, *serverpb.GenericPutRequest) (*serverpb.GenericPutResponse, error) + // Get a Generic template by name. + GenericGet(context.Context, *serverpb.GenericGetRequest) (*serverpb.GenericGetResponse, error) + // Delete a Generic template by name. + GenericDelete(context.Context, *serverpb.GenericDeleteRequest) (*serverpb.GenericDeleteResponse, error) +} + +func RegisterGenericServer(s *grpc.Server, srv GenericServer) { + s.RegisterService(&_Generic_serviceDesc, srv) +} + +func _Generic_GenericPut_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(serverpb.GenericPutRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GenericServer).GenericPut(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/rpcpb.Generic/GenericPut", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GenericServer).GenericPut(ctx, req.(*serverpb.GenericPutRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Generic_GenericGet_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(serverpb.GenericGetRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GenericServer).GenericGet(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/rpcpb.Generic/GenericGet", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GenericServer).GenericGet(ctx, req.(*serverpb.GenericGetRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Generic_GenericDelete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(serverpb.GenericDeleteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GenericServer).GenericDelete(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/rpcpb.Generic/GenericDelete", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GenericServer).GenericDelete(ctx, req.(*serverpb.GenericDeleteRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Generic_serviceDesc = grpc.ServiceDesc{ + ServiceName: "rpcpb.Generic", + HandlerType: (*GenericServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GenericPut", + Handler: _Generic_GenericPut_Handler, + }, + { + MethodName: "GenericGet", + Handler: _Generic_GenericGet_Handler, + }, + { + MethodName: "GenericDelete", + Handler: _Generic_GenericDelete_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "rpc.proto", +} + // Client API for Select service type SelectClient interface { @@ -623,28 +759,31 @@ var _Select_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("rpc.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 365 bytes of a gzipped FileDescriptorProto + // 411 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x94, 0xd1, 0x4e, 0xc2, 0x30, - 0x14, 0x86, 0x85, 0x44, 0x02, 0xc7, 0xe8, 0xc5, 0xee, 0x44, 0x10, 0xe3, 0x03, 0x8c, 0x04, 0xdf, - 0x40, 0x8d, 0x84, 0x84, 0x0b, 0x82, 0xf1, 0x01, 0xd8, 0x72, 0x84, 0x25, 0x40, 0x6b, 0xdb, 0x19, - 0x1f, 0xc9, 0xf8, 0x18, 0xbe, 0x97, 0x89, 0x69, 0xd7, 0x96, 0xb3, 0xad, 0xbd, 0xe2, 0xe4, 0xff, - 0xd6, 0x8f, 0xc3, 0x5f, 0x32, 0x18, 0x08, 0x9e, 0xa7, 0x5c, 0x30, 0xc5, 0x92, 0x73, 0xc1, 0x73, - 0x9e, 0x0d, 0x1f, 0xb7, 0x85, 0xda, 0x95, 0x59, 0x9a, 0xb3, 0xc3, 0x34, 0x67, 0x02, 0x99, 0x9c, - 0x1e, 0x36, 0x2a, 0xdf, 0x65, 0xec, 0xeb, 0x34, 0x48, 0x14, 0x9f, 0x28, 0xec, 0x07, 0xcf, 0xa6, - 0x07, 0x94, 0x72, 0xb3, 0x45, 0x59, 0xa9, 0x66, 0xdf, 0x5d, 0xe8, 0xcd, 0x05, 0x2b, 0xb9, 0x4c, - 0x9e, 0xa0, 0x6f, 0xa6, 0x55, 0xa9, 0x92, 0xeb, 0xd4, 0x1d, 0x48, 0x5d, 0xb6, 0xc6, 0x8f, 0x12, - 0xa5, 0x1a, 0x0e, 0x43, 0x48, 0x72, 0x76, 0x94, 0x78, 0x7f, 0xe6, 0x25, 0x73, 0x6c, 0x4b, 0xe6, - 0x18, 0x95, 0x18, 0xe4, 0x25, 0x4b, 0xb8, 0x30, 0xe9, 0x33, 0xee, 0x51, 0x61, 0x32, 0x6a, 0x3c, - 0x5c, 0xc5, 0x4e, 0x35, 0x8e, 0x50, 0x6f, 0x7b, 0x81, 0x81, 0x01, 0xcb, 0x42, 0xaa, 0xa4, 0xf9, - 0xc5, 0x3a, 0x74, 0xa6, 0x9b, 0x20, 0x73, 0x9e, 0xd9, 0x6f, 0x17, 0xfa, 0x2b, 0xc1, 0xde, 0x8b, - 0x3d, 0xca, 0x64, 0x01, 0x60, 0x67, 0x5d, 0x17, 0x39, 0x79, 0x4a, 0x9d, 0x76, 0x14, 0x86, 0x7e, - 0xbf, 0x93, 0x4a, 0x97, 0xd6, 0x56, 0x91, 0xda, 0x46, 0x61, 0xe8, 0x55, 0x6b, 0xb8, 0xb4, 0xb9, - 0xad, 0xee, 0xb6, 0x75, 0xa0, 0x5e, 0xde, 0x24, 0xca, 0xe9, 0x65, 0x58, 0x64, 0x0a, 0x6c, 0xaf, - 0x40, 0x2b, 0x1c, 0x47, 0xa8, 0x2f, 0xf1, 0xaf, 0x03, 0xfd, 0xc5, 0xf6, 0x58, 0xa8, 0x82, 0x1d, - 0xb5, 0xda, 0xcd, 0xba, 0x45, 0xa2, 0x26, 0x71, 0x40, 0x5d, 0xa3, 0x74, 0x51, 0x07, 0x74, 0x91, - 0x01, 0x1b, 0x69, 0x72, 0x1c, 0xa1, 0xde, 0xf6, 0x06, 0x57, 0x0e, 0xd8, 0x2e, 0x27, 0xed, 0x23, - 0xf5, 0x32, 0xef, 0xe2, 0x0f, 0xf8, 0xdf, 0xff, 0xd3, 0x81, 0xde, 0x2b, 0xee, 0x31, 0x57, 0x7a, - 0xdf, 0x6a, 0x32, 0x7f, 0x36, 0xba, 0x2f, 0x89, 0x03, 0xfb, 0xd6, 0x28, 0xbd, 0xfa, 0x0a, 0xd8, - 0xde, 0xe9, 0xd5, 0xd7, 0x40, 0xe0, 0xea, 0x1b, 0xdc, 0x39, 0xb3, 0x9e, 0x79, 0x47, 0x3c, 0xfc, - 0x07, 0x00, 0x00, 0xff, 0xff, 0x05, 0x60, 0x8e, 0x1b, 0x7b, 0x04, 0x00, 0x00, + 0x14, 0x86, 0x85, 0x44, 0x84, 0x1a, 0xbd, 0xd8, 0x9d, 0x08, 0x62, 0x7c, 0x80, 0x91, 0xe0, 0x1b, + 0xa8, 0x71, 0x21, 0xe1, 0x82, 0x60, 0x7c, 0x00, 0xb6, 0x1c, 0x61, 0x09, 0xac, 0xb3, 0xed, 0x8c, + 0x8f, 0x64, 0x7c, 0x0c, 0x5f, 0xc9, 0x6b, 0x13, 0xd3, 0xae, 0xed, 0xce, 0xd6, 0xf6, 0x8a, 0x93, + 0xff, 0xdb, 0xf9, 0x39, 0xfb, 0xcf, 0x01, 0x32, 0x62, 0x65, 0x16, 0x97, 0x8c, 0x0a, 0x1a, 0x9d, + 0xb2, 0x32, 0x2b, 0xd3, 0xf1, 0xc3, 0x2e, 0x17, 0xfb, 0x2a, 0x8d, 0x33, 0x7a, 0x9c, 0x67, 0x94, + 0x01, 0xe5, 0xf3, 0xe3, 0x56, 0x64, 0xfb, 0x94, 0x7e, 0x36, 0x05, 0x07, 0xf6, 0x01, 0x4c, 0x7f, + 0x94, 0xe9, 0xfc, 0x08, 0x9c, 0x6f, 0x77, 0xc0, 0x6b, 0xab, 0xc5, 0x57, 0x9f, 0x0c, 0x12, 0x46, + 0xab, 0x92, 0x47, 0x8f, 0x64, 0xa8, 0xaa, 0x75, 0x25, 0xa2, 0xab, 0xd8, 0x34, 0xc4, 0x46, 0xdb, + 0xc0, 0x7b, 0x05, 0x5c, 0x8c, 0xc7, 0x3e, 0xc4, 0x4b, 0x5a, 0x70, 0xb8, 0x3b, 0xb1, 0x26, 0x09, + 0xb8, 0x26, 0x09, 0x04, 0x4d, 0x14, 0xb2, 0x26, 0x2b, 0x72, 0xae, 0xd4, 0x27, 0x38, 0x80, 0x80, + 0x68, 0xd2, 0x79, 0xb8, 0x96, 0x8d, 0xd5, 0x34, 0x40, 0xad, 0xdb, 0x33, 0x19, 0x29, 0xb0, 0xca, + 0xb9, 0x88, 0xba, 0x5f, 0x2c, 0x45, 0xe3, 0x74, 0xed, 0x65, 0xc6, 0x67, 0xf1, 0xd3, 0x27, 0xc3, + 0x35, 0xa3, 0x6f, 0xf9, 0x01, 0x78, 0xb4, 0x24, 0x44, 0xd7, 0x32, 0x2e, 0xd4, 0xd9, 0xa8, 0xc6, + 0x76, 0xe2, 0x87, 0x76, 0xbe, 0xc6, 0x4a, 0x86, 0xe6, 0x5a, 0xa1, 0xd8, 0x26, 0x7e, 0x68, 0xad, + 0x36, 0xe4, 0x42, 0xeb, 0x3a, 0xba, 0x1b, 0xa7, 0xa1, 0x1d, 0xde, 0x2c, 0xc8, 0xf1, 0x32, 0x34, + 0x52, 0x01, 0xba, 0x23, 0xe0, 0x08, 0xa7, 0x01, 0x6a, 0x43, 0xfc, 0xeb, 0x91, 0xe1, 0x72, 0x57, + 0xe4, 0x22, 0xa7, 0x85, 0xb4, 0x36, 0xb5, 0x4c, 0x11, 0x59, 0x23, 0xd9, 0x63, 0xdd, 0xa2, 0x78, + 0x50, 0x03, 0x64, 0x90, 0x1e, 0x37, 0x94, 0xe4, 0x34, 0x40, 0xad, 0xdb, 0x2b, 0xb9, 0x34, 0x40, + 0x67, 0x39, 0x73, 0x5b, 0xda, 0x61, 0xde, 0x86, 0x1f, 0xb0, 0xef, 0xff, 0xdb, 0x23, 0x67, 0x09, + 0x14, 0xc0, 0xf2, 0x4c, 0x2e, 0x5e, 0x97, 0x9d, 0x1b, 0x6a, 0x54, 0xcf, 0xe2, 0x31, 0xc4, 0x37, + 0xa4, 0xf5, 0xce, 0x0d, 0x35, 0x6a, 0xd8, 0xca, 0xb9, 0x21, 0xad, 0xbb, 0x37, 0xd4, 0x02, 0x9e, + 0x1b, 0xea, 0x70, 0xfb, 0xd6, 0xdf, 0x3d, 0x32, 0x78, 0x81, 0x03, 0x64, 0x42, 0x6e, 0xa9, 0xae, + 0xd4, 0x4f, 0x0c, 0x6f, 0x09, 0xc9, 0x9e, 0x2d, 0xb5, 0x28, 0x1e, 0xb6, 0x06, 0xfa, 0xda, 0xf0, + 0xb0, 0x2d, 0xe0, 0x19, 0xb6, 0xc3, 0x8d, 0x67, 0x3a, 0x50, 0xff, 0x8c, 0xf7, 0xff, 0x01, 0x00, + 0x00, 0xff, 0xff, 0xf6, 0x7f, 0x75, 0x65, 0x71, 0x05, 0x00, 0x00, } diff --git a/matchbox/rpc/rpcpb/rpc.proto b/matchbox/rpc/rpcpb/rpc.proto index 25ac4f9d..fb8d796e 100644 --- a/matchbox/rpc/rpcpb/rpc.proto +++ b/matchbox/rpc/rpcpb/rpc.proto @@ -26,7 +26,7 @@ service Profiles { } service Ignition { - // Create or update an Container Linux Config template. + // Create or update a Container Linux Config template. rpc IgnitionPut(serverpb.IgnitionPutRequest) returns (serverpb.IgnitionPutResponse) {}; // Get a Container Linux Config template by name. rpc IgnitionGet(serverpb.IgnitionGetRequest) returns (serverpb.IgnitionGetResponse) {}; @@ -34,6 +34,15 @@ service Ignition { rpc IgnitionDelete(serverpb.IgnitionDeleteRequest) returns (serverpb.IgnitionDeleteResponse) {}; } +service Generic { + // Create or update a Generic template. + rpc GenericPut(serverpb.GenericPutRequest) returns (serverpb.GenericPutResponse) {}; + // Get a Generic template by name. + rpc GenericGet(serverpb.GenericGetRequest) returns (serverpb.GenericGetResponse) {}; + // Delete a Generic template by name. + rpc GenericDelete(serverpb.GenericDeleteRequest) returns (serverpb.GenericDeleteResponse) {}; +} + service Select { // SelectGroup returns the Group matching the given labels. rpc SelectGroup(serverpb.SelectGroupRequest) returns (serverpb.SelectGroupResponse) {}; diff --git a/matchbox/server/server.go b/matchbox/server/server.go index ae4ec91c..45fc36f9 100644 --- a/matchbox/server/server.go +++ b/matchbox/server/server.go @@ -49,11 +49,15 @@ type Server interface { // Delete an Ignition template by name. IgnitionDelete(context.Context, *pb.IgnitionDeleteRequest) error + // Create or update an Generic template. + GenericPut(context.Context, *pb.GenericPutRequest) (string, error) + // Get an Generic template by name. + GenericGet(context.Context, *pb.GenericGetRequest) (string, error) + // Delete an Generic template by name. + GenericDelete(context.Context, *pb.GenericDeleteRequest) error + // Get a Cloud-Config template by name. CloudGet(ctx context.Context, name string) (string, error) - - // Get a generic template by name. - GenericGet(ctc context.Context, name string) (string, error) } // Config configures a server implementation. @@ -182,17 +186,31 @@ func (s *server) IgnitionGet(ctx context.Context, req *pb.IgnitionGetRequest) (s return s.store.IgnitionGet(req.Name) } -// IgnitionGet deletes an Ignition template by name. +// IgnitionDelete deletes an Ignition template by name. func (s *server) IgnitionDelete(ctx context.Context, req *pb.IgnitionDeleteRequest) error { return s.store.IgnitionDelete(req.Name) } +// GenericPut creates or updates an Generic template by name. +func (s *server) GenericPut(ctx context.Context, req *pb.GenericPutRequest) (string, error) { + err := s.store.GenericPut(req.Name, req.Config) + if err != nil { + return "", err + } + return string(req.Config), err +} + +// GenericGet gets an Generic template by name. +func (s *server) GenericGet(ctx context.Context, req *pb.GenericGetRequest) (string, error) { + return s.store.GenericGet(req.Name) +} + +// GenericDelete deletes an Generic template by name. +func (s *server) GenericDelete(ctx context.Context, req *pb.GenericDeleteRequest) error { + return s.store.GenericDelete(req.Name) +} + // CloudGet gets a Cloud-Config template by name. func (s *server) CloudGet(ctx context.Context, name string) (string, error) { return s.store.CloudGet(name) } - -// GenericGet gets a generic template by name. -func (s *server) GenericGet(ctx context.Context, name string) (string, error) { - return s.store.GenericGet(name) -} diff --git a/matchbox/server/server_test.go b/matchbox/server/server_test.go index 31d304ef..a7f07f8c 100644 --- a/matchbox/server/server_test.go +++ b/matchbox/server/server_test.go @@ -228,3 +228,38 @@ func TestIgnition_BrokenStore(t *testing.T) { assert.Error(t, err) err = srv.IgnitionDelete(context.Background(), &pb.IgnitionDeleteRequest{Name: fake.IgnitionYAMLName}) } + +func TestGenericCRUD(t *testing.T) { + srv := NewServer(&Config{Store: fake.NewFixedStore()}) + req := &pb.GenericPutRequest{ + Name: fake.GenericName, + Config: []byte(fake.Generic), + } + _, err := srv.GenericPut(context.Background(), req) + // assert that: + // - Generic template creation is successful + // - Generic template can be retrieved by name + // - Generic template can be deleted by name + assert.Nil(t, err) + template, err := srv.GenericGet(context.Background(), &pb.GenericGetRequest{Name: fake.GenericName}) + assert.Equal(t, fake.Generic, template) + assert.Nil(t, err) + + err = srv.GenericDelete(context.Background(), &pb.GenericDeleteRequest{Name: fake.GenericName}) + assert.Nil(t, err) + _, err = srv.GenericGet(context.Background(), &pb.GenericGetRequest{Name: fake.GenericName}) + assert.Error(t, err) +} + +func TestGeneric_BrokenStore(t *testing.T) { + srv := NewServer(&Config{&fake.BrokenStore{}}) + req := &pb.GenericPutRequest{ + Name: fake.GenericName, + Config: []byte(fake.Generic), + } + _, err := srv.GenericPut(context.Background(), req) + assert.Error(t, err) + _, err = srv.GenericGet(context.Background(), &pb.GenericGetRequest{Name: fake.GenericName}) + assert.Error(t, err) + err = srv.GenericDelete(context.Background(), &pb.GenericDeleteRequest{Name: fake.GenericName}) +} diff --git a/matchbox/server/serverpb/messages.pb.go b/matchbox/server/serverpb/messages.pb.go index 9e5d041c..263f622f 100644 --- a/matchbox/server/serverpb/messages.pb.go +++ b/matchbox/server/serverpb/messages.pb.go @@ -35,6 +35,12 @@ It has these top-level messages: IgnitionGetResponse IgnitionDeleteRequest IgnitionDeleteResponse + GenericPutRequest + GenericPutResponse + GenericGetRequest + GenericGetResponse + GenericDeleteRequest + GenericDeleteResponse */ package serverpb @@ -414,6 +420,94 @@ func (m *IgnitionDeleteResponse) String() string { return proto.Compa func (*IgnitionDeleteResponse) ProtoMessage() {} func (*IgnitionDeleteResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } +type GenericPutRequest struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Config []byte `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` +} + +func (m *GenericPutRequest) Reset() { *m = GenericPutRequest{} } +func (m *GenericPutRequest) String() string { return proto.CompactTextString(m) } +func (*GenericPutRequest) ProtoMessage() {} +func (*GenericPutRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } + +func (m *GenericPutRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *GenericPutRequest) GetConfig() []byte { + if m != nil { + return m.Config + } + return nil +} + +type GenericPutResponse struct { +} + +func (m *GenericPutResponse) Reset() { *m = GenericPutResponse{} } +func (m *GenericPutResponse) String() string { return proto.CompactTextString(m) } +func (*GenericPutResponse) ProtoMessage() {} +func (*GenericPutResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } + +type GenericGetRequest struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *GenericGetRequest) Reset() { *m = GenericGetRequest{} } +func (m *GenericGetRequest) String() string { return proto.CompactTextString(m) } +func (*GenericGetRequest) ProtoMessage() {} +func (*GenericGetRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } + +func (m *GenericGetRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +type GenericGetResponse struct { + Config []byte `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` +} + +func (m *GenericGetResponse) Reset() { *m = GenericGetResponse{} } +func (m *GenericGetResponse) String() string { return proto.CompactTextString(m) } +func (*GenericGetResponse) ProtoMessage() {} +func (*GenericGetResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } + +func (m *GenericGetResponse) GetConfig() []byte { + if m != nil { + return m.Config + } + return nil +} + +type GenericDeleteRequest struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *GenericDeleteRequest) Reset() { *m = GenericDeleteRequest{} } +func (m *GenericDeleteRequest) String() string { return proto.CompactTextString(m) } +func (*GenericDeleteRequest) ProtoMessage() {} +func (*GenericDeleteRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } + +func (m *GenericDeleteRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +type GenericDeleteResponse struct { +} + +func (m *GenericDeleteResponse) Reset() { *m = GenericDeleteResponse{} } +func (m *GenericDeleteResponse) String() string { return proto.CompactTextString(m) } +func (*GenericDeleteResponse) ProtoMessage() {} +func (*GenericDeleteResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{31} } + func init() { proto.RegisterType((*SelectGroupRequest)(nil), "serverpb.SelectGroupRequest") proto.RegisterType((*SelectGroupResponse)(nil), "serverpb.SelectGroupResponse") @@ -441,42 +535,50 @@ func init() { proto.RegisterType((*IgnitionGetResponse)(nil), "serverpb.IgnitionGetResponse") proto.RegisterType((*IgnitionDeleteRequest)(nil), "serverpb.IgnitionDeleteRequest") proto.RegisterType((*IgnitionDeleteResponse)(nil), "serverpb.IgnitionDeleteResponse") + proto.RegisterType((*GenericPutRequest)(nil), "serverpb.GenericPutRequest") + proto.RegisterType((*GenericPutResponse)(nil), "serverpb.GenericPutResponse") + proto.RegisterType((*GenericGetRequest)(nil), "serverpb.GenericGetRequest") + proto.RegisterType((*GenericGetResponse)(nil), "serverpb.GenericGetResponse") + proto.RegisterType((*GenericDeleteRequest)(nil), "serverpb.GenericDeleteRequest") + proto.RegisterType((*GenericDeleteResponse)(nil), "serverpb.GenericDeleteResponse") } func init() { proto.RegisterFile("messages.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 500 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x54, 0xdd, 0x4e, 0xdb, 0x30, - 0x14, 0x56, 0xca, 0xe8, 0xd8, 0xe9, 0xc4, 0x8a, 0xdb, 0xb2, 0x8a, 0x2b, 0xe6, 0x4d, 0x28, 0xda, - 0x4f, 0x90, 0xd8, 0xcd, 0x40, 0x42, 0x62, 0x6c, 0x15, 0x9a, 0xc4, 0x05, 0xea, 0x9e, 0x20, 0x09, - 0x87, 0x10, 0x2d, 0x89, 0xb3, 0xd8, 0x41, 0xe3, 0x31, 0x76, 0xb1, 0xf7, 0x9d, 0xea, 0x1c, 0x27, - 0x4e, 0xe8, 0xaa, 0x55, 0xe2, 0xaa, 0xce, 0xc9, 0x77, 0xbe, 0x3f, 0xb7, 0x85, 0xed, 0x14, 0xa5, - 0xf4, 0x23, 0x94, 0x5e, 0x5e, 0x08, 0x25, 0xd8, 0x96, 0xc4, 0xe2, 0x0e, 0x8b, 0x3c, 0xd8, 0xfb, - 0x12, 0xc5, 0xea, 0xb6, 0x0c, 0xbc, 0x50, 0xa4, 0x87, 0xa1, 0x28, 0x50, 0xc8, 0xc3, 0xd4, 0x57, - 0xe1, 0x6d, 0x20, 0x7e, 0x35, 0x07, 0xa9, 0x44, 0xe1, 0x47, 0x68, 0x3e, 0xf3, 0xc0, 0x9c, 0x2a, - 0x3a, 0xfe, 0xdb, 0x01, 0xf6, 0x1d, 0x13, 0x0c, 0xd5, 0x45, 0x21, 0xca, 0x7c, 0x8e, 0x3f, 0x4b, - 0x94, 0x8a, 0x9d, 0x41, 0x3f, 0xf1, 0x03, 0x4c, 0xe4, 0xd4, 0xd9, 0xdf, 0x70, 0x07, 0x47, 0xae, - 0x67, 0x64, 0xbd, 0x87, 0x68, 0xef, 0x52, 0x43, 0x67, 0x99, 0x2a, 0xee, 0xe7, 0xb4, 0xb7, 0x77, - 0x0c, 0x03, 0x6b, 0xcc, 0x86, 0xb0, 0xf1, 0x03, 0xef, 0xa7, 0xce, 0xbe, 0xe3, 0x3e, 0x9b, 0x2f, - 0x8e, 0x6c, 0x0c, 0x9b, 0x77, 0x7e, 0x52, 0xe2, 0xb4, 0xa7, 0x67, 0xd5, 0xc3, 0x49, 0xef, 0x93, - 0xc3, 0x4f, 0x61, 0xd4, 0x12, 0x91, 0xb9, 0xc8, 0x24, 0xb2, 0x03, 0xd8, 0x8c, 0x16, 0x03, 0x4d, - 0x32, 0x38, 0x1a, 0x7a, 0x75, 0x26, 0xaf, 0x02, 0x56, 0xaf, 0xf9, 0x1f, 0x07, 0xc6, 0xd5, 0xfe, - 0x55, 0x21, 0x6e, 0xe2, 0x04, 0x4d, 0xa8, 0xf3, 0x4e, 0xa8, 0xb7, 0xdd, 0x50, 0x6d, 0xfc, 0x63, - 0xc7, 0x9a, 0xc1, 0xa4, 0x23, 0x43, 0xc1, 0xde, 0xc3, 0xd3, 0xbc, 0x1a, 0x51, 0x34, 0x66, 0x45, - 0x33, 0x60, 0x03, 0xe1, 0xc7, 0xf0, 0x42, 0xc7, 0xbd, 0x2a, 0x95, 0x09, 0xf6, 0xbf, 0xcd, 0x30, - 0x18, 0x36, 0xab, 0x95, 0x38, 0x7f, 0x45, 0x74, 0x17, 0x58, 0xd3, 0x6d, 0x43, 0x2f, 0xbe, 0xa6, - 0x4c, 0xbd, 0xf8, 0x9a, 0x9f, 0xd0, 0x9a, 0x86, 0xac, 0x79, 0x19, 0x6f, 0x80, 0xe9, 0xe7, 0xaf, - 0x98, 0xa0, 0xc2, 0x7f, 0x29, 0x4c, 0x60, 0xd4, 0x42, 0x91, 0x37, 0xe3, 0xf7, 0x32, 0x96, 0xc6, - 0x1c, 0x3f, 0x85, 0x1d, 0x6b, 0x46, 0x6e, 0x5c, 0xe8, 0x6b, 0x39, 0x73, 0xb3, 0x0f, 0xed, 0xd0, - 0x7b, 0xfe, 0x19, 0x76, 0xa8, 0x51, 0xab, 0xbf, 0xf5, 0x2e, 0x60, 0x0c, 0xcc, 0xa6, 0x20, 0xaf, - 0xaf, 0x6b, 0xe2, 0x15, 0x4d, 0x9e, 0xd7, 0xab, 0x76, 0x97, 0xeb, 0xc9, 0x1f, 0xc0, 0x98, 0x66, - 0xab, 0x3b, 0x7d, 0x09, 0x93, 0x0e, 0x8e, 0x9c, 0x36, 0xfe, 0xed, 0x5e, 0x67, 0x30, 0x6a, 0x4d, - 0xc9, 0x9b, 0x07, 0x5b, 0x24, 0x6c, 0xba, 0x5d, 0x66, 0xae, 0xc6, 0xf0, 0x33, 0x60, 0xdf, 0xa2, - 0x2c, 0x56, 0xb1, 0xc8, 0xac, 0x82, 0x19, 0x3c, 0xc9, 0xfc, 0x14, 0xc9, 0x9d, 0x3e, 0xb3, 0x5d, - 0xe8, 0x87, 0x22, 0xbb, 0x89, 0x23, 0xfd, 0x4b, 0x79, 0x3e, 0xa7, 0xa7, 0xc5, 0x77, 0xa1, 0xc5, - 0x40, 0xae, 0xdd, 0x86, 0xd8, 0x2a, 0x78, 0x09, 0x31, 0xff, 0xd0, 0x10, 0xd8, 0x2d, 0x37, 0x7a, - 0x4e, 0x4b, 0xef, 0x1d, 0x4c, 0x0c, 0xbc, 0x5d, 0xe8, 0x32, 0xee, 0x29, 0xec, 0x76, 0xc1, 0x15, - 0x7d, 0xd0, 0xd7, 0xff, 0xa7, 0x1f, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x31, 0x28, 0x4b, 0x3d, - 0xb0, 0x05, 0x00, 0x00, + // 538 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x55, 0x6f, 0x4f, 0xd3, 0x40, + 0x18, 0x4f, 0x87, 0x4c, 0x7c, 0x30, 0xb8, 0xdd, 0x3a, 0x58, 0x78, 0x85, 0xa7, 0xc1, 0x05, 0xb1, + 0x24, 0xf8, 0x46, 0x48, 0x88, 0x88, 0x2e, 0x8b, 0x09, 0x2f, 0xc8, 0xfc, 0x04, 0x6d, 0x79, 0x28, + 0x8d, 0x5d, 0xaf, 0xf6, 0x6e, 0x44, 0x3e, 0x86, 0x2f, 0xfc, 0xbe, 0x66, 0xd7, 0xe7, 0xda, 0x6b, + 0x99, 0xc0, 0x8c, 0xaf, 0x76, 0x7d, 0xfa, 0x7b, 0x7e, 0xff, 0x6e, 0xcb, 0x60, 0x63, 0x8a, 0x52, + 0xfa, 0x11, 0x4a, 0x2f, 0xcb, 0x85, 0x12, 0x6c, 0x4d, 0x62, 0x7e, 0x83, 0x79, 0x16, 0x6c, 0x7f, + 0x8e, 0x62, 0x75, 0x3d, 0x0b, 0xbc, 0x50, 0x4c, 0x0f, 0x42, 0x91, 0xa3, 0x90, 0x07, 0x53, 0x5f, + 0x85, 0xd7, 0x81, 0xf8, 0x59, 0x1d, 0xa4, 0x12, 0xb9, 0x1f, 0xa1, 0xf9, 0xcc, 0x02, 0x73, 0x2a, + 0xe8, 0xf8, 0x2f, 0x07, 0xd8, 0x37, 0x4c, 0x30, 0x54, 0xe3, 0x5c, 0xcc, 0xb2, 0x09, 0xfe, 0x98, + 0xa1, 0x54, 0xec, 0x14, 0xda, 0x89, 0x1f, 0x60, 0x22, 0x07, 0xce, 0xce, 0xca, 0x70, 0xfd, 0x70, + 0xe8, 0x19, 0x59, 0xef, 0x2e, 0xda, 0x3b, 0xd7, 0xd0, 0x51, 0xaa, 0xf2, 0xdb, 0x09, 0xed, 0x6d, + 0x1f, 0xc1, 0xba, 0x35, 0x66, 0x1d, 0x58, 0xf9, 0x8e, 0xb7, 0x03, 0x67, 0xc7, 0x19, 0x3e, 0x9b, + 0xcc, 0x8f, 0xcc, 0x85, 0xd5, 0x1b, 0x3f, 0x99, 0xe1, 0xa0, 0xa5, 0x67, 0xc5, 0xc3, 0x71, 0xeb, + 0x83, 0xc3, 0x4f, 0xa0, 0x57, 0x13, 0x91, 0x99, 0x48, 0x25, 0xb2, 0x5d, 0x58, 0x8d, 0xe6, 0x03, + 0x4d, 0xb2, 0x7e, 0xd8, 0xf1, 0xca, 0x4c, 0x5e, 0x01, 0x2c, 0x5e, 0xf3, 0xdf, 0x0e, 0xb8, 0xc5, + 0xfe, 0x45, 0x2e, 0xae, 0xe2, 0x04, 0x4d, 0xa8, 0xb3, 0x46, 0xa8, 0xbd, 0x66, 0xa8, 0x3a, 0xfe, + 0x7f, 0xc7, 0x1a, 0x41, 0xbf, 0x21, 0x43, 0xc1, 0xf6, 0xe1, 0x69, 0x56, 0x8c, 0x28, 0x1a, 0xb3, + 0xa2, 0x19, 0xb0, 0x81, 0xf0, 0x23, 0x78, 0xa1, 0xe3, 0x5e, 0xcc, 0x94, 0x09, 0xf6, 0xd8, 0x66, + 0x18, 0x74, 0xaa, 0xd5, 0x42, 0x9c, 0xbf, 0x24, 0xba, 0x31, 0x96, 0x74, 0x1b, 0xd0, 0x8a, 0x2f, + 0x29, 0x53, 0x2b, 0xbe, 0xe4, 0xc7, 0xb4, 0xa6, 0x21, 0x4b, 0x5e, 0xc6, 0x6b, 0x60, 0xfa, 0xf9, + 0x0b, 0x26, 0xa8, 0xf0, 0x6f, 0x0a, 0x7d, 0xe8, 0xd5, 0x50, 0xe4, 0xcd, 0xf8, 0x3d, 0x8f, 0xa5, + 0x31, 0xc7, 0x4f, 0xa0, 0x6b, 0xcd, 0xc8, 0xcd, 0x10, 0xda, 0x5a, 0xce, 0xdc, 0xec, 0x5d, 0x3b, + 0xf4, 0x9e, 0x7f, 0x82, 0x2e, 0x35, 0x6a, 0xf5, 0xb7, 0xdc, 0x05, 0xb8, 0xc0, 0x6c, 0x0a, 0xf2, + 0xfa, 0xaa, 0x24, 0xbe, 0xa7, 0xc9, 0xb3, 0x72, 0xd5, 0xee, 0x72, 0x39, 0xf9, 0x5d, 0x70, 0x69, + 0x76, 0x7f, 0xa7, 0x5b, 0xd0, 0x6f, 0xe0, 0xc8, 0x69, 0xe5, 0xdf, 0xee, 0x75, 0x04, 0xbd, 0xda, + 0x94, 0xbc, 0x79, 0xb0, 0x46, 0xc2, 0xa6, 0xdb, 0x45, 0xe6, 0x4a, 0x0c, 0x3f, 0x05, 0xf6, 0x35, + 0x4a, 0x63, 0x15, 0x8b, 0xd4, 0x2a, 0x98, 0xc1, 0x93, 0xd4, 0x9f, 0x22, 0xb9, 0xd3, 0x67, 0xb6, + 0x09, 0xed, 0x50, 0xa4, 0x57, 0x71, 0xa4, 0x7f, 0x29, 0xcf, 0x27, 0xf4, 0x34, 0xff, 0x2e, 0xd4, + 0x18, 0xc8, 0xf5, 0xb0, 0x22, 0xb6, 0x0a, 0x5e, 0x40, 0xcc, 0xdf, 0x55, 0x04, 0x76, 0xcb, 0x95, + 0x9e, 0x53, 0xd3, 0x7b, 0x0b, 0x7d, 0x03, 0xaf, 0x17, 0xba, 0x88, 0x7b, 0x00, 0x9b, 0x4d, 0x30, + 0xf9, 0xfb, 0x08, 0xdd, 0x31, 0xa6, 0x98, 0xc7, 0xe1, 0x3f, 0xe6, 0x76, 0x81, 0xd9, 0x04, 0x44, + 0xfb, 0xa6, 0xa4, 0x7d, 0x20, 0xf5, 0x7e, 0xb9, 0xfe, 0x98, 0xd0, 0x7b, 0xe0, 0x12, 0xfa, 0xe1, + 0xcc, 0x5b, 0xd0, 0x6f, 0x60, 0x0b, 0xf2, 0xa0, 0xad, 0xff, 0x42, 0xde, 0xff, 0x09, 0x00, 0x00, + 0xff, 0xff, 0x8d, 0x61, 0x17, 0x92, 0xa3, 0x06, 0x00, 0x00, } diff --git a/matchbox/server/serverpb/messages.proto b/matchbox/server/serverpb/messages.proto index 672707a6..206a3de0 100644 --- a/matchbox/server/serverpb/messages.proto +++ b/matchbox/server/serverpb/messages.proto @@ -3,6 +3,8 @@ package serverpb; import "github.com/coreos/matchbox/matchbox/storage/storagepb/storage.proto"; +// Selects + message SelectGroupRequest { map labels = 1; } @@ -67,6 +69,8 @@ message ProfileListResponse { repeated storagepb.Profile profiles = 1; } +// Ignition + message IgnitionPutRequest { string name = 1; bytes config = 2; @@ -84,3 +88,23 @@ message IgnitionDeleteRequest { string name = 1; } message IgnitionDeleteResponse {} + +// Generic + +message GenericPutRequest { + string name = 1; + bytes config = 2; +} +message GenericPutResponse {} + +message GenericGetRequest { + string name = 1; +} +message GenericGetResponse { + bytes config = 1; +} + +message GenericDeleteRequest { + string name = 1; +} +message GenericDeleteResponse {} diff --git a/matchbox/storage/filestore.go b/matchbox/storage/filestore.go index 4656f6ef..36ffa79e 100644 --- a/matchbox/storage/filestore.go +++ b/matchbox/storage/filestore.go @@ -146,14 +146,24 @@ func (s *fileStore) IgnitionDelete(name string) error { return Dir(s.root).deleteFile(filepath.Join("ignition", name)) } +// GenericPut creates or updates an Generic template. +func (s *fileStore) GenericPut(name string, config []byte) error { + return Dir(s.root).writeFile(filepath.Join("generic", name), config) +} + +// GenericGet gets an Generic template by name. +func (s *fileStore) GenericGet(name string) (string, error) { + data, err := Dir(s.root).readFile(filepath.Join("generic", name)) + return string(data), err +} + +// GenericDelete deletes an Generic template by name. +func (s *fileStore) GenericDelete(name string) error { + return Dir(s.root).deleteFile(filepath.Join("generic", name)) +} + // CloudGet gets a Cloud-Config template by name. func (s *fileStore) CloudGet(name string) (string, error) { data, err := Dir(s.root).readFile(filepath.Join("cloud", name)) return string(data), err } - -// GenericGet gets a generic template by name. -func (s *fileStore) GenericGet(name string) (string, error) { - data, err := Dir(s.root).readFile(filepath.Join("generic", name)) - return string(data), err -} diff --git a/matchbox/storage/filestore_test.go b/matchbox/storage/filestore_test.go index 6f46494d..35a6ec1b 100644 --- a/matchbox/storage/filestore_test.go +++ b/matchbox/storage/filestore_test.go @@ -187,6 +187,45 @@ func TestIgnitionGet(t *testing.T) { assert.Nil(t, err) } +func TestGenericCRUD(t *testing.T) { + dir, err := setup(&fake.FixedStore{}) + assert.Nil(t, err) + defer os.RemoveAll(dir) + + store := NewFileStore(&Config{Root: dir}) + // assert that: + // - Generic template creation was successful + // - Generic template can be retrieved by name + // - Generic template can be deleted by name + err = store.GenericPut(fake.GenericName, []byte(fake.Generic)) + assert.Nil(t, err) + + template, err := store.GenericGet(fake.GenericName) + assert.Nil(t, err) + assert.Equal(t, fake.Generic, template) + + err = store.GenericDelete(fake.GenericName) + assert.Nil(t, err) + _, err = store.GenericGet(fake.GenericName) + if assert.Error(t, err) { + assert.IsType(t, err, &os.PathError{}) + } +} + +func TestGenericGet(t *testing.T) { + contents := `{"ignitionVersion":1,"storage":{},"systemd":{"units":[{"name":"etcd2.service","enable":true}]},"networkd":{},"passwd":{}}` + dir, err := setup(&fake.FixedStore{ + GenericConfigs: map[string]string{"generic": contents}, + }) + assert.Nil(t, err) + defer os.RemoveAll(dir) + + store := NewFileStore(&Config{Root: dir}) + ign, err := store.GenericGet("generic") + assert.Equal(t, contents, ign) + assert.Nil(t, err) +} + func TestCloudGet(t *testing.T) { contents := "#cloud-config" dir, err := setup(&fake.FixedStore{ @@ -213,8 +252,9 @@ func setup(fixedStore *fake.FixedStore) (root string, err error) { profileDir := filepath.Join(root, "profiles") groupDir := filepath.Join(root, "groups") ignitionDir := filepath.Join(root, "ignition") + genericDir := filepath.Join(root, "generic") cloudDir := filepath.Join(root, "cloud") - if err := mkdirs(profileDir, groupDir, ignitionDir, cloudDir); err != nil { + if err := mkdirs(profileDir, groupDir, ignitionDir, genericDir, cloudDir); err != nil { return root, err } // files @@ -251,6 +291,13 @@ func setup(fixedStore *fake.FixedStore) (root string, err error) { return root, err } } + for name, content := range fixedStore.GenericConfigs { + genericFile := filepath.Join(genericDir, name) + err = ioutil.WriteFile(genericFile, []byte(content), defaultFileMode) + if err != nil { + return root, err + } + } for name, content := range fixedStore.CloudConfigs { cloudConfigFile := filepath.Join(cloudDir, name) err = ioutil.WriteFile(cloudConfigFile, []byte(content), defaultFileMode) diff --git a/matchbox/storage/storage.go b/matchbox/storage/storage.go index b77ab05b..a795f952 100644 --- a/matchbox/storage/storage.go +++ b/matchbox/storage/storage.go @@ -39,9 +39,13 @@ type Store interface { // IgnitionDelete deletes an Ignition template by name. IgnitionDelete(name string) error + // GenericPut creates or updates a Generic template. + GenericPut(name string, config []byte) error + // GenericGet gets a Generic template by name. + GenericGet(name string) (string, error) + // GenericDelete deletes a Generic template by name. + GenericDelete(name string) error + // CloudGet gets a Cloud-Config template by name. CloudGet(name string) (string, error) - - // GenericGet gets a generic template by name. - GenericGet(name string) (string, error) } diff --git a/matchbox/storage/testfakes/broken_store.go b/matchbox/storage/testfakes/broken_store.go index 798488a4..5d713e62 100644 --- a/matchbox/storage/testfakes/broken_store.go +++ b/matchbox/storage/testfakes/broken_store.go @@ -68,12 +68,22 @@ func (s *BrokenStore) IgnitionDelete(name string) error { return errIntentional } -// CloudGet returns an error. -func (s *BrokenStore) CloudGet(name string) (string, error) { - return "", errIntentional +// GenericPut returns an error. +func (s *BrokenStore) GenericPut(name string, config []byte) error { + return errIntentional } // GenericGet returns an error. func (s *BrokenStore) GenericGet(name string) (string, error) { return "", errIntentional } + +// GenericDelete returns an error. +func (s *BrokenStore) GenericDelete(name string) error { + return errIntentional +} + +// CloudGet returns an error. +func (s *BrokenStore) CloudGet(name string) (string, error) { + return "", errIntentional +} diff --git a/matchbox/storage/testfakes/empty_store.go b/matchbox/storage/testfakes/empty_store.go index 392bc944..21e9a71b 100644 --- a/matchbox/storage/testfakes/empty_store.go +++ b/matchbox/storage/testfakes/empty_store.go @@ -64,12 +64,22 @@ func (s *EmptyStore) IgnitionDelete(name string) error { return nil } +// GenericPut returns an error writing any Generic template. +func (s *EmptyStore) GenericPut(name string, config []byte) error { + return fmt.Errorf("emptyStore does not accept Generic templates") +} + +// GenericGet get returns an Generic template not found error. +func (s *EmptyStore) GenericGet(name string) (string, error) { + return "", fmt.Errorf("no Generic template %s", name) +} + +// GenericDelete returns a nil error (successful deletion). +func (s *EmptyStore) GenericDelete(name string) error { + return nil +} + // CloudGet returns a Cloud-config template not found error. func (s *EmptyStore) CloudGet(name string) (string, error) { return "", fmt.Errorf("no Cloud-Config template %s", name) } - -// GenericGet returns a generic template not found error. -func (s *EmptyStore) GenericGet(name string) (string, error) { - return "", fmt.Errorf("no generic template %s", name) -} diff --git a/matchbox/storage/testfakes/fixed_store.go b/matchbox/storage/testfakes/fixed_store.go index c36dd565..22c5c312 100644 --- a/matchbox/storage/testfakes/fixed_store.go +++ b/matchbox/storage/testfakes/fixed_store.go @@ -108,6 +108,26 @@ func (s *FixedStore) IgnitionDelete(name string) error { return nil } +// GenericPut create or updates an Generic template. +func (s *FixedStore) GenericPut(name string, config []byte) error { + s.GenericConfigs[name] = string(config) + return nil +} + +// GenericGet returns an Generic template by name. +func (s *FixedStore) GenericGet(name string) (string, error) { + if config, present := s.GenericConfigs[name]; present { + return config, nil + } + return "", fmt.Errorf("no Generic template %s", name) +} + +// GenericDelete deletes an Generic template by name. +func (s *FixedStore) GenericDelete(name string) error { + delete(s.GenericConfigs, name) + return nil +} + // CloudGet returns a Cloud-config template by name. func (s *FixedStore) CloudGet(name string) (string, error) { if config, present := s.CloudConfigs[name]; present { @@ -115,11 +135,3 @@ func (s *FixedStore) CloudGet(name string) (string, error) { } return "", fmt.Errorf("no Cloud-Config template %s", name) } - -// GenericGet returns a generic template by name. -func (s *FixedStore) GenericGet(name string) (string, error) { - if config, present := s.GenericConfigs[name]; present { - return config, nil - } - return "", fmt.Errorf("no generic template %s", name) -} diff --git a/matchbox/storage/testfakes/fixtures.go b/matchbox/storage/testfakes/fixtures.go index 2290a320..1778a4db 100644 --- a/matchbox/storage/testfakes/fixtures.go +++ b/matchbox/storage/testfakes/fixtures.go @@ -46,5 +46,13 @@ systemd: units: - name: etcd2.service enable: true +` + + // GenericName is a Generic template name for testing. + GenericName = "generic.tmpl" + + // Generic is a Generic template for testing. + Generic = ` +This is a generic template. ` )